通常我们在开发中会遇到这样的情况,在一个TextView中使不同的文字有不同的颜色、大小、超链接等,通常有两种方法可以实现这个效果,1、Spannable;2、HTML.fromHTML();这两种方法都可以实现如下效果。
HTML.fromHTML()方法能实现这种比较简单的,但是对于复杂的超链接、插入图片等操作就不太适用,所以这里我悬着了Spannable来实现这个效果。
我的需求是比较规则的数字、中文组成的字符串,所以我做成了通用的一个方法,根据规律方法实现如下:
调用方法:
changeStyle(("4小时50分钟"), 0.5f)
方法实现:
/**
* 给不同的字设置不同的颜色、大小
*
* @param timeStr 字符串
* @param proportion 文字缩放比例
* @return
*/
private SpannableStringBuilder changeStyle(String timeStr, float proportion) {
SpannableStringBuilder ssb = new SpannableStringBuilder(timeStr);
if (TextUtils.isEmpty(timeStr)) {
return ssb;
}
int tvColor = mContext.getResources().getColor(R.color.bra_gray);//字体需要设置的颜色
//将数字与汉字分割存在在数组中
List<String> lStr = new ArrayList<String>();
Pattern p = Pattern.compile("[\\u4e00-\\u9fa5]+|[\\d|\\.]*\\d+");
Matcher m = p.matcher(timeStr);
while (m.find()) {
lStr.add(m.group());
}
int start = 0, end = 0;
for (int i = 1, len = lStr.size(); i < len; i += 2) {
start = end + lStr.get(i - 1).length();//起始位置从上一次循环结束位置+当前字符长度
end = start + lStr.get(i).length();
ssb.setSpan(new ForegroundColorSpan(tvColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new RelativeSizeSpan(proportion), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return ssb;
}
创建完Spannable对象后,就可以为它们设置Span来实现想要的Rich Text了,常见的Span有:
- AbsoluteSizeSpan(int size) ---- 设置字体大小,参数是绝对数值,相当于Word中的字体大小
- RelativeSizeSpan(float proportion) ---- 设置字体大小,参数是相对于默认字体大小的倍数,比如默认字体大小是x, 那么设置后的字体大小就是x*proportion,这个用起来比较灵活,proportion>1就是放大(zoom in), proportion<1就是缩小(zoom out)
- ScaleXSpan(float proportion) ---- 缩放字体,与上面的类似,默认为1,设置后就是原来的乘以proportion,大于1时放大(zoon in),小于时缩小(zoom out)
- BackgroundColorSpan(int color) ----背景着色,参数是颜色数值,可以直接使用android.graphics.Color里面定义的常量,或是用Color.rgb(int, int, int)
- ForegroundColorSpan(int color) ----前景着色,也就是字的着色,参数与背景着色一致
- TypefaceSpan(String family) ----字体,参数是字体的名字比如“sans", "sans-serif"等
- StyleSpan(Typeface style) -----字体风格,比如粗体,斜体,参数是android.graphics.Typeface里面定义的常量,如Typeface.BOLD,Typeface.ITALIC等等。
- StrikethroughSpan----如果设置了此风格,会有一条线从中间穿过所有的字,就像被划掉一样
对于这些Sytle span在使用的时候通常只传上面所说明的构造参数即可,不需要设置其他的属性,如果需要的话,也可以对它们设置其他的属性,详情可以参见 <文档>。
Spannable的使用资料:http://www.cnblogs.com/weixiong-wang/p/4046313.html
在我开发的时候在字符串的分割的时候弄了很长时间;
一开始我一直使用的split()来切分的字符串,这种方法切分字符串会把分隔符直接干掉,不存在于分割之后的数组里面,比如“abc,12ji,jiji”;当我们使用str.split(",")进行分割的时候得到的是{"abc","12ji","12ji"};这么一个数组,但是我这的需求是要将","还要保留下来的,所以这种方法无法实现我所需要的效果。
后面改用了正则表达式来做
Matcher m = p.matcher(timeStr);
while (m.find()) {
lStr.add(m.group());
}
他会根据我们的匹配条件来分组,而不会将符合条件的字符直接干掉;
关于正则表达式中Pattern类与Matcher类的使用:http://blog.csdn.net/kofandlizi/article/details/7323863
这里讲得比较详细;