如何清除URLSpan点击效果?

时间:2014-02-15 23:25:33

标签: android textview urlspan

背景

我想在textView中使用一些URLSpan,所以我使用了类似的东西:

final Spanned spanned=Html.fromHtml(getString(R.string.test));
msgTextView.setText(spanned);

问题

它有效,但点击某个项目时,它会一直点击。就像我仍然触摸链接一样......

我尝试了什么

我试图从textView中清除焦点并将焦点设置在另一个视图上,但这些都没有帮助。

我还尝试删除UrlSpan并添加一个新的,每次点击它,但它不起作用。这是代码:

  public static Spannable setOnLinkClickedListener(final Spanned original,final IOnLinkClickListener listener)
    {
    final SpannableString result=new SpannableString(original);
    final URLSpan[] spans=result.getSpans(0,result.length(),URLSpan.class);
    for(final URLSpan span : spans)
      {
      final int start=result.getSpanStart(span);
      final int end=result.getSpanEnd(span);
      final int flags=result.getSpanFlags(span);
      result.removeSpan(span);
      final String url=span.getURL();
      result.setSpan(new CustomURLSpan(url,start,result,end,listener,flags),start,end,flags);
      }
    return result;
    }

  private static final class CustomURLSpan extends URLSpan
    {
    private final int                  _start;
    private final SpannableString      _result;
    private final String               _url;
    private final int                  _end;
    private final IOnLinkClickListener _listener;
    private final int                  _flags;

    private CustomURLSpan(final String url,final int start,final SpannableString result,final int end,final IOnLinkClickListener listener,final int flags)
      {
      super(url);
      _start=start;
      _result=result;
      _url=url;
      _end=end;
      _listener=listener;
      _flags=flags;
      }

    @Override
    public void onClick(final View widget)
      {
      if(_listener==null||!_listener.onClick(widget,_url))
        super.onClick(widget);
      _result.removeSpan(this);
      _result.setSpan(new CustomURLSpan(_url,_start,_result,_end,_listener,_flags),_start,_end,_flags);
      }
    }

问题

如何清除每次点击时留在URLSpan上的选择/点击效果?

3 个答案:

答案 0 :(得分:0)

之前我遇到过同样的问题。它可能是因为您正在使用的textView的text:textIsSelectable属性。删除它或将其设置为false,它将被解决。

答案 1 :(得分:0)

子类LinkMovementMethod并覆盖onTouchEvent以在Selection.removeSelection(buffer);之后调用link[0].onClick(widget);

// 1. Subclass LinkMovementMethod.
public class CustomLinkMovementMethod extends LinkMovementMethod {

    // 2. Copy this method from LinkMovementMethod.
    @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);
                    Selection.removeSelection(buffer); // 3. Add this line.
                } else if (action == MotionEvent.ACTION_DOWN) {
                    Selection.setSelection(buffer,
                            buffer.getSpanStart(link[0]),
                            buffer.getSpanEnd(link[0]));
                }

                return true;
            } else {
                Selection.removeSelection(buffer);
            }
        }

        return super.onTouchEvent(widget, buffer, event);
    }
}

BTW,如果您在ListView,子类TextView中使用它并覆盖setPressed来致电invalidate();,因为ListView推迟调用setPressed

public class CustomTextView extends TextView {

    public CustomTextView(Context context) {
        super(context);
    }

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setPressed(boolean pressed) {
        super.setPressed(pressed);
        invalidate();
    }
}

答案 2 :(得分:0)

this answer对我有用。我在API19 API26中使用Checkbox进行测试,CheckedTexView TextView全部澄清