textview文本片段点击事件与textview点击事件冲突执行两次(最终解决办法)
2017-07-11 14:53
501 查看
开发项目中遇到 需要在一个textview中能够点击@好友跳转 用的是下面的方法:
但是写好后发现 再点击“@好友“之后会同时执行上面的ClickableSpan的onClick方法和textview的监听器onClick方法。
百思不得其解,在网上搜了一下午都找不到满意的答案,看来都是你抄我的我抄你的,抄来抄去,看着都生气;
最后还是国外某个网站上搜到的,虽然英文不咋好,还是跌跌撞撞搜到了答案;o(╯□╰)o (不说废话了,直接上答案):
在你的代码上加上:[/code]
2
3
4
5
6
7
8
9
10
只需要上面这一个就可以了,下面两个也不用加了:
SpannableString nameSpan = new SpannableString(name); nameSpan.setSpan(new ClickableSpan() { @Override public void onClick(View widget) { // TODO Auto-generated method stub } }, 0, nameSpan.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
但是写好后发现 再点击“@好友“之后会同时执行上面的ClickableSpan的onClick方法和textview的监听器onClick方法。
百思不得其解,在网上搜了一下午都找不到满意的答案,看来都是你抄我的我抄你的,抄来抄去,看着都生气;
最后还是国外某个网站上搜到的,虽然英文不咋好,还是跌跌撞撞搜到了答案;o(╯□╰)o (不说废话了,直接上答案):
import android.text.Layout; import android.text.NoCopySpan; import android.text.Selection; import android.text.Spannable; import android.text.method.MovementMethod; import android.text.method.ScrollingMovementMethod; import android.text.style.ClickableSpan; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; public class CustomLinkMovementMethod extends ScrollingMovementMethod { private static final int CLICK = 1; private static final int UP = 2; private static final int DOWN = 3; public abstract interface TextClickedListener { public abstract void onTextClicked(); } TextClickedListener listener = null; public void setOnTextClickListener(TextClickedListener listen){ listener = listen; } @Override public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: case KeyEvent.KEYCODE_ENTER: if (event.getRepeatCount() == 0) { if (action(CLICK, widget, buffer)) { return true; } } } return super.onKeyDown(widget, buffer, keyCode, event); } @Override protected boolean up(TextView widget, Spannable buffer) { if (action(UP, widget, buffer)) { return true; } return super.up(widget, buffer); } @Override protected boolean down(TextView widget, Spannable buffer) { if (action(DOWN, widget, buffer)) { return true; } return super.down(widget, buffer); } @Override protected boolean left(TextView widget, Spannable buffer) { if (action(UP, widget, buffer)) { return true; } return super.left(widget, buffer); } @Override protected boolean right(TextView widget, Spannable buffer) { if (action(DOWN, widget, buffer)) { return true; } return super.right(widget, buffer); } private boolean action(int what, TextView widget, Spannable buffer) { boolean handled = false; Layout layout = widget.getLayout(); int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); int areatop = widget.getScrollY(); int areabot = areatop + widget.getHeight() - padding; int linetop = layout.getLineForVertical(areatop); int linebot = layout.getLineForVertical(areabot); int first = layout.getLineStart(linetop); int last = layout.getLineEnd(linebot); ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class); int a = Selection.getSelectionStart(buffer); int b = Selection.getSelectionEnd(buffer); int selStart = Math.min(a, b); int selEnd = Math.max(a, b); if (selStart < 0) { if (buffer.getSpanStart(FROM_BELOW) >= 0) { selStart = selEnd = buffer.length(); } } if (selStart > last) selStart = selEnd = Integer.MAX_VALUE; if (selEnd < first) selStart = selEnd = -1; switch (what) { case CLICK: if (selStart == selEnd) { return false; } ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class); if (link.length != 1) return false; link[0].onClick(widget); break; case UP: int beststart, bestend; beststart = -1; bestend = -1; for (int i = 0; i < candidates.length; i++) { int end = buffer.getSpanEnd(candidates[i]); if (end < selEnd || selStart == selEnd) { if (end > bestend) { beststart = buffer.getSpanStart(candidates[i]); bestend = end; } } } if (beststart >= 0) { Selection.setSelection(buffer, bestend, beststart); return true; } break; case DOWN: beststart = Integer.MAX_VALUE; bestend = Integer.MAX_VALUE; for (int i = 0; i < candidates.length; i++) { int start = buffer.getSpanStart(candidates[i]); if (start > selStart || selStart == selEnd) { if (start < beststart) { beststart = start; bestend = buffer.getSpanEnd(candidates[i]); } } } if (bestend < Integer.MAX_VALUE) { Selection.setSelection(buffer, beststart, bestend); return true; } break; } return false; } public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) { return false; } @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } return true; } else { Selection.removeSelection(buffer); if (action == MotionEvent.ACTION_UP) { if(listener != null) listener.onTextClicked(); } } } return super.onTouchEvent(widget, buffer, event); } public void initialize(TextView widget, Spannable text) { Selection.removeSelection(text); text.removeSpan(FROM_BELOW); } public void onTakeFocus(TextView view, Spannable text, int dir) { Selection.removeSelection(text); if ((dir & View.FOCUS_BACKWARD) != 0) { text.setSpan(FROM_BELOW, 0, 0, Spannable.SPAN_POINT_POINT); } else { text.removeSpan(FROM_BELOW); } } public static MovementMethod getInstance() { if (sInstance == null) sInstance = new CustomLinkMovementMethod(); return sInstance; } private static CustomLinkMovementMethod sInstance; private static Object FROM_BELOW = new NoCopySpan.Concrete(); }
在你的代码上加上:[/code]
CustomLinkMovementMethod link = (CustomLinkMovementMethod)CustomLinkMovementMethod.getInstance(); //textview默认的点击事件可以写在这里,也可以另写(写在这里貌似会有点混乱) link.setOnTextClickListener(new CustomLinkMovementMethod.TextClickedListener() { @Override public void onTextClicked() { Toast.makeText(UserProfileActivity.this, "text Pressed", Toast.LENGTH_LONG).show(); } }); YOUR_TEXTVIEW.setMovementMethod(link);1
2
3
4
5
6
7
8
9
10
只需要上面这一个就可以了,下面两个也不用加了:
YOUR_TEXTVIEW.setMovementMethod(ScrollingMovementMethod.getInstance());//滑动 YOUR_TEXTVIEW.setMovementMethod(LinkMovementMethod.getInstance());//开始响应点击事件
相关文章推荐
- textview文本片段点击事件与textview点击事件冲突执行两次(最终解决办法)
- Tap手势与UITableView点击事件冲突解决办法
- SpannableString中的ClickableSpan和Textview点击事件冲突解决
- TableView cell的选中事件 与手势点击事件 冲突解决办法
- (转载)js(jquery)的on绑定点击事件执行两次的解决办法
- AutoCompleteTextView 设置了点击事件需要点击两下解决办法
- 从ScrollView嵌套EditText的滑动事件冲突分析触摸事件的分发机制以及TextView的简要实现和冲突的解决办法
- TextView点击事件不响应解决办法
- 在ListView中的Text添加spannableString 点击事件与ListView的OnItemClick事件冲突的解决办法
- 背景视图上点击事件与tableView冲突的解决办法
- 从ScrollView嵌套EditText的滑动事件冲突分析触摸事件的分发机制以及TextView的简要实现和冲突的解决办法
- ViewGrop 滑动与 子View点击事件冲突解决办法
- Android TextView 给文本中指定片段添加自定义点击事件
- android 自定义TextView支持微博功能后在ListView占用了Item点击的解决办法
- ListView中的Item点击事件和子控件的冲突或者item点击没有反应的解决办法
- 开发笔记:解决安卓GestureOverlayView手势和ListView点击事件、文本框获取焦点冲突的问题
- Android Listview中Button按钮点击事件冲突解决办法
- JQUERY $() $(document).ready() 事件执行两次解决办法。
- IOS7 UITableView一行滑动删除后 被删除行的下一行的点击事件将被忽略解决办法
- listview中textview响应部分文本点击事件