美文网首页
ClickableSpan

ClickableSpan

作者: 要学的东西太多了 | 来源:发表于2020-03-30 14:21 被阅读0次
    • ClickableSpan要生效,需要给textview设置MovementMethod,否则点击是不生效的。在texview的setMovementMethod方法里面,会赋值给mMovement变量,在textview的ontouchevent方法里面有如下判断:
    if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
                    && mText instanceof Spannable && mLayout != null) {
                boolean handled = false;
                if (mMovement != null) {
                    handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
                }
                final boolean textIsSelectable = isTextSelectable();
                //这里一般来说不会走,因为mAutoLinkMask 默认是0,一般也不会去设值
                if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) {
                    ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
                        getSelectionEnd(), ClickableSpan.class);
                    if (links.length > 0) {
                        links[0].onClick(this);
                        handled = true;
                    }
                }
    //、、、
    }
    

    如果没设置,不会回调mMovement.onTouchEvent方法,也不会调用里面ClickableSpan的onClick方法,代码如下:

    @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[] links = buffer.getSpans(off, off, ClickableSpan.class);
    
                if (links.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                        links[0].onClick(widget);
                    } else if (action == MotionEvent.ACTION_DOWN) {
                        Selection.setSelection(buffer,
                            buffer.getSpanStart(links[0]),
                            buffer.getSpanEnd(links[0]));
                    }
                    return true;
                } else {
                    Selection.removeSelection(buffer);
                }
            }
    
            return super.onTouchEvent(widget, buffer, event);
        }
    
    • ClickableSpan默认是有下划线的,而且点击后背景色不会变回来,要去掉下划线并实现点击后的背景恢复,需要重写ClickableSpan和LinkMovementMethod,实现如下:
      去下划线:
    public abstract class MyClickable extends ClickableSpan {
        private int color;
        private boolean underline = false;
        public MyClickable(int color){
            this.color = color;
        }
        public MyClickable(boolean underline, int color){
            this.color = color;
            this.underline = underline;
        }
        @Override
        public void updateDrawState(TextPaint ds) {
            ds.setColor(color);//画笔颜色
            ds.setUnderlineText(underline);//是否有下划线
        }
    }
    

    背景恢复:

    public class MyLInkMovementMethod extends LinkMovementMethod {
        private static MyLInkMovementMethod instance;
    
        public static MyLInkMovementMethod getInstance(){
            if(instance==null){
                instance = new MyLInkMovementMethod();
            }
            return instance;
        }
    
        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
            int action = event.getAction();
            if (action == MotionEvent.ACTION_UP) {
                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){
                    link[0].onClick(widget);
                    //在抬起的时候,重新设置span的背景色,这里也可以做其他操作,比如按下的颜色等等
                    buffer.setSpan(new BackgroundColorSpan(Color.TRANSPARENT),
                            buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]),
                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    Selection.removeSelection(buffer);
                    return true;
                }
            }
            return super.onTouchEvent(widget, buffer, event);
        }
    }
    

    相关文章

      网友评论

          本文标题:ClickableSpan

          本文链接:https://www.haomeiwen.com/subject/tfcvuhtx.html