很多App中都会涉及到:在TextView中设置不同颜色的字体并且部分字体会存在点击事件。
在Android中主要通过ClickableSpan类来实现这一功能,其实这个实现没有任何技巧,只不过自己在实现的时候遇到一个坑(坑会在下文指出),特以此记录一下。
在Google官方API文档中这样解释ClickableSpan:
If an object of this type is attached to the text of a TextView with a movement method of LinkMovementMethod, the affected spans of text can be selected. If clicked, theonClick(View)method will be called.
大致意思是:如果将该类的(ClickableSpan)对象与TextView的文本连接在一起,并且TextView设置了LinkMovementMethod方法,则可以选择受影响的文本范围。如果需要点击,则需要调用onClick(View)方法。其中的“受影响的文本”,就是你想要的有不同颜色或者有点击效果的文本了。
从ClickableSpan继承的父类来看
extends CharacterStyle implements UpdateAppearance
↳android.text.style.CharacterStyle
↳android.text.style.ClickableSpan
ClickableSpan类同BackgroundColorSpan(背景色)、ForegroundColorSpan(前景色暨字体颜色)、UnderlineSpan(下划线)等类用法相似,都是为TextView下的文本设置不同Style的。在明白了ClickableSpan的作用以及出处后,接下来的事情就是马代码了。
自定义类继承ClickableSpan,重写其中的onClick(View widget)、updateDrawState(TextPaint ds)方法(此处有坑!此处有坑!此处有坑!重要的事情说三遍)。因为之前有看到文章在这个方法下面去使用TextPaint下的setColor(int color)方法给部分字体设置颜色,作为菜鸡的我就这样去试了,但是颜色和自己设置的却有差别,不得不找问题出在哪儿(还以为UI给错色值了.....)。
查看抽象类ClickableSpan源码:
/**
* If an object of this type is attached to the text of a TextView
* with a movement method of LinkMovementMethod, the affected spans of
* text can be selected. If clicked, the {@link#onClick} method will
* be called.
*/
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance{
/**
* Performs the click action associated with this span.
*/
public abstract voidonClick(View widget);
/**
* Makes the text underlined and in the link color.
*/
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(true);
}
}
源码给出的解释是可以设置链接的颜色,所以我猜测会不会因为它本身已经设置了一个颜色,再次设置的话就会覆盖导致出现差别。
public class MyClickableSpan extends ClickableSpan {
private String str;
private Context context;
pulbic MyClickabelSpan(String str, Context context){
this.str = str;
this.context = context;
}
@Override
public void updateDrawState(TextPaint ds) {
//ds.setColor(Color.BULE) 通过这里设置出来的颜色有差别
}
@Override
public void onClick(View widget) {
//这里的判断是为了去掉在点击后字体出现的背景色
if(widget instanceof TextView){
((TextView)widget).setHighlightColor(Color.TRANSPARENT);
}
//在这里写下你想要的点击效果
context.startActivity(newIntent(context,AgreementActivity.class));
}
}
在定义好类之后,就可以在TextView上进行设置了,代码如下:
TextView mText;
mText = (TextView) findViewById(R.id.XXX);
String str = "想要设置成不同颜色或者有点击事件的字符串"
SpannableString span = new SpannableString(str);
ClickableSpan clickSpan = new MyClickableSpan(str, this);
span.setSpan(clickSpan, 0, str.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
//在这里通过ForegroundColorSpan来给部分字体设置颜色。可以设置成功
span.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.XXX)), 0, str.length(),Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
mText.setText("正常部分的字符串");
mText.append(span);
mText.setMovementMethod(LinkMovementMethod.getInstance()); //这个必须有,API对ClickableSpan类的解释里面便提到了:在TextView设置了此方法的前提下,才能选择受影响的文本范围。
通过以上的实现,基本可以满足TextView设置不同颜色等样式的需求。
网友评论