TextView的ClickableSpan、OnClickListener、OnLongClickListener冲突的问题

TextView的富文本带来了很多便利,但也带了不少坑,本篇主要解决设置了ClickableSpan、OnClickListener、OnLongClickListener带来的问题。
我们先来看ClickableSpan、OnClickListener的坑,我们会发现,我们点击的是Span部分,ClickableSpan的onClick会被执行,但OnClickListener也会执行onClick方法,是不是很刺激啊,其实最好的办法是在ClickableSpan的onClick被执行时,不要执行OnClickListener 的onClick方法就行了(哈哈,那不是废话吗)
所以,我们自定义OnTouchListener监听TextView的事件,来拦截Touch自行处理行为:

public class CustomTextViewTouchListener implements View.OnTouchListener {

    private View.OnClickListener mOnClickListener;

    public CustomTextViewTouchListener(View.OnClickListener onClickListener) {
        mOnClickListener = onClickListener;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();
        TextView tv = (TextView) v;
        CharSequence text = tv.getText();
        if (action == MotionEvent.ACTION_UP) {
            if (text instanceof Spanned) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                x -= tv.getTotalPaddingLeft();
                y -= tv.getTotalPaddingTop();
                x += tv.getScrollX();
                y += tv.getScrollY();
                Layout layout = tv.getLayout();
                int line = layout.getLineForVertical(y);
                int off = layout.getOffsetForHorizontal(line, x);
                ClickableSpan[] link = ((Spanned) text).getSpans(off, off, ClickableSpan.class);
                if (link.length != 0) {
                    link[0].onClick(tv);
                } else {
                    //do textview click event
                    if (null != mOnClickListener) {
                        mOnClickListener.onClick(v);
                    }
                }
            } else {
                if (null != mOnClickListener) {
                    mOnClickListener.onClick(v);
                }
            }
        }
        return true;
    }
}

这样我们就解决了ClickableSpan、OnClickListener会一起执行的问题,但是这样的话,我们给TextView设置了长按事件OnLongClickListener就没办法工作了,所以我们还需在原来的代码上做个修改,如下:

public class IMCustomTouchListener implements View.OnTouchListener {

    private long mLastActionDownTime = -1;
    private View mView;

    private Handler mHandler = new Handler(Looper.getMainLooper());

    private Runnable mLongClickRunnable = new Runnable() {
        @Override
        public void run() {
            if (mView != null) {
                mView.performLongClick();
            }
        }
    };

    private void removeLongClickRunnable() {
        mHandler.removeCallbacksAndMessages(null);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();
        TextView tv = (TextView) v;
        CharSequence text = tv.getText();
        if (action != MotionEvent.ACTION_MOVE) {
            removeLongClickRunnable();
        }
        if (action == MotionEvent.ACTION_DOWN) {
            mLastActionDownTime = System.currentTimeMillis();
            this.mView = v;
            mHandler.postDelayed(mLongClickRunnable, ViewConfiguration.getLongPressTimeout());
        } else {
            long actionUpTime = System.currentTimeMillis();
            if (actionUpTime - mLastActionDownTime >= ViewConfiguration.getLongPressTimeout()) {
                //v.performLongClick();
                return true;
            }
            if (action == MotionEvent.ACTION_UP) {
                if (text instanceof Spanned) {
                    int x = (int) event.getX();
                    int y = (int) event.getY();
                    x -= tv.getTotalPaddingLeft();
                    y -= tv.getTotalPaddingTop();
                    x += tv.getScrollX();
                    y += tv.getScrollY();
                    Layout layout = tv.getLayout();
                    int line = layout.getLineForVertical(y);
                    int off = layout.getOffsetForHorizontal(line, x);
                    ClickableSpan[] link = ((Spanned) text).getSpans(off, off, ClickableSpan.class);
                    if (link.length != 0) {
                        link[0].onClick(tv);
                    } else {
                        //do textview click event
                        v.performClick();
                    }
                } else {
                    v.performClick();
                }
            }
        }
        return true;
    }
}

完美解决…

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值