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 CustomTextViewTouchListener implements View.OnTouchListener {

    private View.OnClickListener mOnClickListener;
    private View.OnLongClickListener mOnLongClickListener;

    private long mLastActionDownTime = -1;

    public CommentTextViewTouchListener(View.OnClickListener onClickListener, View.OnLongClickListener onLongClickListener) {
        mOnClickListener = onClickListener;
        mOnLongClickListener = onLongClickListener;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();
        TextView tv = (TextView) v;
        CharSequence text = tv.getText();
        if (action == MotionEvent.ACTION_DOWN) {
            mLastActionDownTime = System.currentTimeMillis();
        } else {
            long actionUpTime = System.currentTimeMillis();
            if (actionUpTime - mLastActionDownTime >= ViewConfiguration.getLongPressTimeout() && null != mOnLongClickListener) {
                mOnLongClickListener.onLongClick(v);
                return false;
            }
            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;
    }
}

完美解決…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章