Android 神器之SpanableString实现textview部分字体点击事件(不同颜色),并且支持多个点击事件

时间:2024-03-15 20:04:21

1.老规矩,咱们先上效果图
Android 神器之SpanableString实现textview部分字体点击事件(不同颜色),并且支持多个点击事件

2.如上图 标红的地方,我们一眼看上去 就是一个TextView上面展示出来的(没错就是一个TextView展示出来的),并且 部分字体颜色不一样,而且这个三个协议是可以点击的,点击跳转到不同页面,怎么实现尼 ?,这里就涉及到一个知识点SpannableString:

    @BindView(R.id.tvIssue)
    TextView tvIssue;
    private int highlightTextNormalColor;
    private int highlightTextPressedColor;
    private int highlightBgNormalColor;
    private int highlightBgPressedColor;
    
   private void initView() {
        highlightTextNormalColor = ContextCompat.getColor(this, R.color.register_text);
        highlightTextPressedColor = ContextCompat.getColor(this, R.color.register_text);
        highlightBgNormalColor = QMUIResHelper.getAttrColor(this, R.attr.actionBarDivider);
        highlightBgPressedColor = QMUIResHelper.getAttrColor(this, R.attr.actionBarDivider);
        tvIssue.setMovementMethod(LinkMovementMethod.getInstance());
        tvIssue.setText(generateSp("注册即表示同意用户注册协议、商户服务协议和隐私权政策"));
    }

    private SpannableString generateSp(String text) {
        String highlight1 = "用户注册协议";
        String highlight2 = "商户服务协议";
        String highlight3 = "隐私权政策";
        SpannableString sp = new SpannableString(text);
        int start = 0, end;
        int index;
        while ((index = text.indexOf(highlight1, start)) > -1) {
            end = index + highlight1.length();
            sp.setSpan(new QMUITouchableSpan(highlightTextNormalColor, highlightTextPressedColor,
                    highlightBgNormalColor, highlightBgPressedColor) {
                @Override
                public void onSpanClick(View widget) {
                    WebViewActivity.skip(RegisterActivity.this, Constent.USERPROTOCOL_URL, "注册协议");
                }
            }, index, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            start = end;
        }
        start = 0;
        while ((index = text.indexOf(highlight2, start)) > -1) {
            end = index + highlight2.length();
            sp.setSpan(new QMUITouchableSpan(highlightTextNormalColor, highlightTextPressedColor,
                    highlightBgNormalColor, highlightBgPressedColor) {
                @Override
                public void onSpanClick(View widget) {
                    WebViewActivity.skip(RegisterActivity.this, Constent.PRIVACYSERVICE_URL, "服务协议");
                }
            }, index, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            start = end;
        }
        start = 0;
        while ((index = text.indexOf(highlight3, start)) > -1) {
            end = index + highlight3.length();
            sp.setSpan(new QMUITouchableSpan(highlightTextNormalColor, highlightTextPressedColor,
                    highlightBgNormalColor, highlightBgPressedColor) {
                @Override
                public void onSpanClick(View widget) {
                    WebViewActivity.skip(RegisterActivity.this, Constent.PRIVACY_URL, "隐私政策");
                }
            }, index, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            start = end;
        }
        return sp;
    }
    //工具类1
    public class QMUIResHelper {

    public static float getAttrFloatValue(Context context, int attrRes){
        TypedValue typedValue = new TypedValue();
        context.getTheme().resolveAttribute(attrRes, typedValue, true);
        return typedValue.getFloat();
    }

    public static int getAttrColor(Context context, int attrRes){
        TypedValue typedValue = new TypedValue();
        context.getTheme().resolveAttribute(attrRes, typedValue, true);
        return typedValue.data;
    }
}
//工具2
/**
 * 可 Touch 的 Span,在 {@link #setPressed(boolean)} 后根据是否 pressed 来触发不同的UI状态
 * <p>
 * 提供设置 span 的文字颜色和背景颜色的功能, 在构造时传入
 * </p>
 */
public abstract class QMUITouchableSpan extends ClickableSpan implements ITouchableSpan {
    private boolean mIsPressed;
    @ColorInt private int mNormalBackgroundColor;
    @ColorInt private int mPressedBackgroundColor;
    @ColorInt private int mNormalTextColor;
    @ColorInt private int mPressedTextColor;

    private boolean mIsNeedUnderline = false;

    public abstract void onSpanClick(View widget);

    @Override
    public final void onClick(View widget) {
        if (ViewCompat.isAttachedToWindow(widget)) {
            onSpanClick(widget);
        }
    }


    public QMUITouchableSpan(@ColorInt int normalTextColor,
                             @ColorInt int pressedTextColor,
                             @ColorInt int normalBackgroundColor,
                             @ColorInt int pressedBackgroundColor) {
        mNormalTextColor = normalTextColor;
        mPressedTextColor = pressedTextColor;
        mNormalBackgroundColor = normalBackgroundColor;
        mPressedBackgroundColor = pressedBackgroundColor;
    }

    public int getNormalBackgroundColor() {
        return mNormalBackgroundColor;
    }

    public void setNormalTextColor(int normalTextColor) {
        mNormalTextColor = normalTextColor;
    }

    public void setPressedTextColor(int pressedTextColor) {
        mPressedTextColor = pressedTextColor;
    }

    public int getNormalTextColor() {
        return mNormalTextColor;
    }

    public int getPressedBackgroundColor() {
        return mPressedBackgroundColor;
    }

    public int getPressedTextColor() {
        return mPressedTextColor;
    }
    
    public void setPressed(boolean isSelected) {
        mIsPressed = isSelected;
    }

    public boolean isPressed() {
        return mIsPressed;
    }

    public void setIsNeedUnderline(boolean isNeedUnderline) {
        mIsNeedUnderline = isNeedUnderline;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setColor(mIsPressed ? mPressedTextColor : mNormalTextColor);
        ds.bgColor = mIsPressed ? mPressedBackgroundColor
                : mNormalBackgroundColor;
        ds.setUnderlineText(mIsNeedUnderline);
    }
}

3.以上代码就可以完美实现Textview显示部分字体颜色更改并且跳转,好啦,代码也比较简单,就分享到这里,有任何问题欢迎留言!