在项目中如果想要给TextView的某一段字进行设置不同的样式,诸如超链接,粗体斜体等效果,有如下两种方式进行设置:
- 使用Html.fromHtml()进行css样式的设置
- 使用SpannableString(SpannableStringBuilder)来进行设置效果
目前在项目中遇到一个问题,即需要用不同的字体库来展示不同的文字,由于需要在客户端进行处理,所以很自然想到SpannableStringBuilder方式来进行处理,只要设置对应的Span即TypefaceSpan就可以了,关于各种Span的介绍,可以看如下的文章,总结的挺好的:
之所以需要用到不同的字体库是因为一些特殊的字符编码,Android本身的字体库是不支持的,显示不出来,所以选择了不同的字体库来进行加载,看下效果:
String prefix = "阿斯顿发生大法师";
String text = "\uE01F\uE060\uE0B7\uE0BE\uE534\uE548\uE549\uE54E\uE54F\uE550\uE551\uE558\uE559\uE55A\uE55B\uE55D\uE55E\uE571\uE573\uE575\uE578\uE579\uE57A\uE581\uE5B2\uE617\uE628\uE631\uE63B\uE63C\uE640\uE649\uE659\uE677\uE697\uE6A1\uE6A3\uE6A6\uE6A7\uE6A8\uE6A9\uE6AA\uE6AB\uE6AC\uE6AD\uE6AE\uE6AF\uE6B1\uE6B2\uE6B3\uE6B5\uE6B6\uE6B9\uE6BA\uE6BC\uE6BF\uE6C0\uE6C7\uE6D1\uE6D8\uE6E5\uE6E7\uE6E9\uE770\uE771\uE781\uE788\uE7AF\uE7B0\uE7B2\uE7B3";
String append = "ad121@#$%大法师打发是点击ad121@#$%大法师打发是点击ad121@#$%大法师打发是点击ad121@#$%大法师打发是点击ad121@#$%大法师打发是点击ad121@#$%大法师打发是点击ad121@#$%大法师打发是点击";
private void change(){
Typeface typeface = Typeface.createFromAsset(getAssets(), "对应字体.ttf");
SpannableStringBuilder builder = new SpannableStringBuilder(prefix + text + append);
builder.setSpan(new CustomTypefaceSpan("", typeface), prefix.length(), prefix.length() + text.length() - 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
normalText.setText(builder);
}
由于TypefaceSpan是一个抽象类,所以我们需要自己去实现这个方法,在stackflow或者github中已经有人放出源码了,直接使用即可:
效果图如下:
可以看到效果图中的字体是展示成功了,但是由于不同的字体库的字体宽高是不一样的,所以,这种效果项目中根本是使用不了了,那么解决的方法也有,就是在系统也提供了对应的修改行高的方法,即LineHeightSpan接口,我们只要对当前TextView设置一个对应的统一行高就可以了:
public class CommonLineSpan implements LineHeightSpan {
@Override
public void chooseHeight(CharSequence text, int start, int end,
int spanstartv, int v, Paint.FontMetricsInt fm) {
fm.descent = 50;
fm.top = -80;
fm.ascent = -79;
fm.bottom = 51;
}
}
上述的fm对应的参数如下图:
图片来源:http://www.jianshu.com/p/2e3889eaec63
然后在代码中加上下面Span就可以展示了:
LineHeightSpan lineHeightSpan = new CommonLineSpan();
builder.setSpan(lineHeightSpan, 0, text.length() - 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
最终效果图: