ClickSpan实现TextView部分文字变色和点击

866 阅读1分钟

简单记录一下天几天做的一个类似隐私协议的部分按钮变色并且可以点击的实现过程

先看下布局文件

布局文件没啥好写的,就是日常见到的类似 已阅读并同意《XXX协议》之类的样式

<TextView
    android:id="@+id/tv_xieyi01"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="4dp"
    android:text="已阅读并同意xxx"
    android:textSize="12dp"
    app:layout_constraintStart_toEndOf="@+id/logins_xieyi"
    app:layout_constraintTop_toTopOf="@+id/logins_xieyi"
    app:layout_constraintEnd_toEndOf="parent"
    android:layout_marginEnd="23dp"
    android:ellipsize="end"/>
<TextView
    android:id="@+id/tv_xieyi01"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="4dp"
    android:text="《用户协议》《隐私政策》"
    android:textSize="12dp"
    app:layout_constraintStart_toEndOf="@+id/logins_xieyi"
    app:layout_constraintTop_toTopOf="@+id/logins_xieyi"
    app:layout_constraintEnd_toEndOf="parent"
    android:layout_marginEnd="23dp"
    android:ellipsize="end"/>

更改显示样式

首先获取到要操作的目标字符串。

以《用户协议》这部分为例,由于这一部分是一个字符串,String类型并没有提供直接对其进行操作的方法,我们可以通过新建一个StringBuilder来操作目标字符串。

SpannableStringBuilder style1 = new SpannableStringBuilder();
style1.append(beforeStr1);

修改《用户协议》的文字颜色。

通过上面的SpannableStringBuilder类可以获取到一个可以直接操作的字符串,然后就可以设置这个字符串的字体颜色了。

//设置部分文字颜色
ForegroundColorSpan foregroundColorSpan1 = new ForegroundColorSpan(getResources().getColor(R.color.xieyi));
//将颜色值设置到刚刚创建的SpannableStringBuilder对象中
style1.setSpan(foregroundColorSpan1, 0, 6, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

设置点击事件。

类似隐私协议之类的显示效果不仅仅是改变部分文字的字体颜色,还要求同一个字符串只有协议名称部分可以点击,这同样也是通过操作创建的SpannableStringBuilder对象实现的。

ClickableSpan clickableSpan1= new ClickableSpan(){
    @Override
    public void onClick(@NonNull View widget) {
        String[] keys={"title","url"};
        String[] values={mBinding.tvXieyi01.getText().toString(), server_url};
        gotoWeb(keys,values);
    }
    @Override
    public void updateDrawState(@NonNull TextPaint ds) {
        ...
    }
};

这样就基本实现了类似底部隐私协议的效果,既改变了《用户协议》几个字的颜色,也给这几个字单独添加了点击事件,但是显示出来会有默认的背景色和一条下划线。我们在重写的updateDrawState方法中添加两行代码就可以解决

ds.setColor(ds.linkColor);
ds.setUnderlineText(false);