阅读 2118

TextView添加SpannableString并添加点击色

最近项目中遇到一个问题,就是一段文字中股票可点击并跳到电话,只记得SpannableString可以实现富文本功能,但并不知道可实现的富文本有点击功能,就开始借助万能搜索引擎,结果不出意料,的确有ClickableSpan这个类可实现点击功能,于是就开始查找Android api ClickableSpan,废话不说了上代码

        TextView tv = (TextView) findViewById(R.id.tv_other_report);
        String content = "This is a text,click me" ;
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new Clickable(v -> {
                //做点击需要的事情
                }), start, end,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv.setMovementMethod(LinkMovementMethod.getInstance());//必须设置否则无法点击
        tv.setHighlightColor(getResources().getColor(android.R.color.transparent));//不设置该属性,点击后会有背景色
        tv.setText(spannableString);复制代码

下面设置点击事件的监听

 /**
     * 内部类,用于截获点击富文本后的事件
     */
    class Clickable extends ClickableSpan implements View.OnClickListener {
        private final View.OnClickListener mListener;

        public Clickable(View.OnClickListener mListener) {
            this.mListener = mListener;
        }

        @Override
        public void onClick(View v) {
            mListener.onClick(v);
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            //设置点击区域的颜色
            ds.setColor(getResources().getColor(R.color.back_text_color_selector));
            ds.setUnderlineText(false);    //去除超链接的下划线
            ds.clearShadowLayer();//清除阴影
        }
    }复制代码

如何设置文字点击色

private class LinkTouchMovementMethod extends LinkMovementMethod {
    private TouchableSpan mPressedSpan;

    @Override
    public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            mPressedSpan = getPressedSpan(textView, spannable, event);
            if (mPressedSpan != null) {
                mPressedSpan.setPressed(true);
                Selection.setSelection(spannable, spannable.getSpanStart(mPressedSpan),
                        spannable.getSpanEnd(mPressedSpan));
            }
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            TouchableSpan touchedSpan = getPressedSpan(textView, spannable, event);
            if (mPressedSpan != null && touchedSpan != mPressedSpan) {
                mPressedSpan.setPressed(false);
                mPressedSpan = null;
                Selection.removeSelection(spannable);
            }
        } else {
            if (mPressedSpan != null) {
                mPressedSpan.setPressed(false);
                super.onTouchEvent(textView, spannable, event);
            }
            mPressedSpan = null;
            Selection.removeSelection(spannable);
        }
        return true;
    }

    private TouchableSpan getPressedSpan(TextView textView, Spannable spannable, MotionEvent event) {

        int x = (int) event.getX();
        int y = (int) event.getY();

        x -= textView.getTotalPaddingLeft();
        y -= textView.getTotalPaddingTop();

        x += textView.getScrollX();
        y += textView.getScrollY();

        Layout layout = textView.getLayout();
        int line = layout.getLineForVertical(y);
        int off = layout.getOffsetForHorizontal(line, x);

        TouchableSpan[] link = spannable.getSpans(off, off, TouchableSpan.class);
        TouchableSpan touchedSpan = null;
        if (link.length > 0) {
            touchedSpan = link[0];
        }
        return touchedSpan;
    }

}复制代码

这需要将应用到 TextView 像这样:

yourTextView.setMovementMethod(new LinkTouchMovementMethod());

这是编辑基于由 LinkTouchMovementMethod 设置的按下状态的绘制状态修改的 ClickableSpan: (它也会删除下划线的链接)

public abstract class TouchableSpan extends ClickableSpan {
    private boolean mIsPressed;
    private int mPressedBackgroundColor;
    private int mNormalTextColor;
    private int mPressedTextColor;

    public TouchableSpan(int normalTextColor, int pressedTextColor, int pressedBackgroundColor) {
        mNormalTextColor = normalTextColor;
        mPressedTextColor = pressedTextColor;
        mPressedBackgroundColor = pressedBackgroundColor;
    }

    public void setPressed(boolean isSelected) {
        mIsPressed = isSelected;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setColor(mIsPressed ? mPressedTextColor : mNormalTextColor);
        ds.bgColor = mIsPressed ? mPressedBackgroundColor : 0xffeeeeee;
        ds.setUnderlineText(false);
    }
}复制代码