我们用xml布局的时候,一个TextView通常只能拥有一个显示样式,如textSize,textColor等.当需要想突出显示TextView中的一些字符或文本的话,应该怎么办呢?
<h2>string.xml</h2>
在string.xml 中,我们可以对字符串做一些简单的样式更改,如下
将wall 的字体颜色置为红色,大小置为50sp
<string name="color"> Humpty Dumpty sat on a <font fgcolor="-#10000" size='50'>wall</font></string>
tips:
- 红色的颜色代码为
#FFFFFFFF
,但如果直接设为fgcolor="#ffff0000"
则不能奏效,甚至会导致目标文本消失. 这是由于颜色的16进制值导致的,简单的方法就是取值为0x100000000 -0xffff0000= 0x10000
再取反,就能成功设置为红色. - size中的值单位为dp
<h2>Html.fromHtml()</h2>
较简易的方法是用Html语法,再使用Html.fromHtml() 转化为有样式的字符串,如下
mTextView.setText(Html.fromHtml("<font color='#cc0029'>Some</font> radom Color"));
<h2>自定义Span</h2>
Spanned 是 CharSequence 的子类,这意味着它也可以在TextVIew中显示,Android 中有各种类型的span
-
AbsoluteSizeSpan
指定字体大小 -
BackgroundColorSpan
指定文本背景色 -
BulletSpan
在文本前显示圆点 ,类似html中的<li>
效果 -
DrawableMarginSpan
,IconMarginSpan
,ImageSpan
文本中添加图片 -
ForegroundColorSpan
改变字体颜色 -
LeadingMarginSpan
调整文本缩进 -
ScaleXSpan
横向缩放文本 -
StrikethroughSpan
添加删除线 -
StyleSpan
添加 正常,粗体,斜体样式 -
SubscriptSpan
下标样式 -
SuperscriptSpan
上标样式 -
TextAppearanceSpan
按照资源中的样式表R.style.my_style
来为文本添加样式 -
TypefaceSpan
设置字体 -
UnderlineSpan
下划线样式 -
URLSpan
可点击打开链接 -
ClickableSpan
抽象类,可以自定义文本点击方法
注意,设置span比较消耗资源,如果可以,在后台线程中操作再设置到控件中.
构建自定义span
主要用到的是SpannableString
和SpannableStringBuilder
这两个类
一般用法就是 先创建所需的Span
,再用setSpan()
方法来进行设置.
<h3>tips:</h3>
-
ClickableSpan
点击后会出现文本背景色发生变化的情况, 可以在onClick
事件中设置控件重绘来解决,如下
public class LinkClickSpan extends ClickableSpan {
AffLinkModel mLinkModel;
public LinkClickSpan(AffLinkModel linkModel) {
mLinkModel = linkModel;
}
@Override
public void onClick(View widget) {
Logger.t("method").i("click");
AffLinkDialog.getInstance(mLinkModel).show(getChildFragmentManager(), null);
widget.invalidate();
}
}
- 如果想用正则表达式将一段文本中特定文本标记或替换,可以使用这个类
Replacer
,如下
/**
* 文本正则替换器
* 支持替换将包含"<...>","[...]"的文本,变为去掉括号,并修改颜色和字体大小
* Author: yanhao(amosbake@gmail.com)
* Date : 2016-01-14
* Time: 15:21
*/
public class Replacer {
private static final String TAG = "Replacer";
private final CharSequence mSource;//需要修改的文本
private final CharSequence mReplacement;//待替换的文本
private final Matcher mMatcher;//正则匹配器
private int mAppendPosition;//当前builder所在位置
private final boolean mIsSpannable;//代替换的样式字符串是否存在样式
//将符合正则的文本替换为指定文本
public static CharSequence replace(CharSequence source,String regex, CharSequence replacement){
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(source);
return new Replacer(matcher,replacement,source).doReplace();
}
//将符合正则的文本替换为指定文本 并修改字体大小和字体颜色
public static CharSequence replaceWithColorAndSize(CharSequence source,String regex,int color,int sizeIndp){
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(source);
return new Replacer(matcher,null,source).doOriginReplace(color,sizeIndp);
}
public Replacer(Matcher matcher, CharSequence replacement, CharSequence source) {
mMatcher = matcher;
mReplacement = replacement;
mSource = source;
mAppendPosition = 0;
mIsSpannable = replacement instanceof Spannable;
}
//执行简单替换的功能
private CharSequence doReplace() {
SpannableStringBuilder builder = new SpannableStringBuilder();
while (mMatcher.find()) {
appendRelacement(builder);
}
return appendTail(builder);
}
//执行替换原文本,并指定替换的字体大小和颜色
private CharSequence doOriginReplace(int color,int textSize){
SpannableStringBuilder builder = new SpannableStringBuilder();
while (mMatcher.find()) {
try {
CharSequence charSource = mSource.subSequence(mMatcher.start()+1, mMatcher.end()-1);
//更换字体颜色
ForegroundColorSpan colorSpan=new ForegroundColorSpan(color);
//更换字体大小
AbsoluteSizeSpan sizeSpan=new AbsoluteSizeSpan(textSize,false);
SpannableStringBuilder stringBuilder=new SpannableStringBuilder(charSource);
stringBuilder.setSpan(colorSpan, 0, charSource.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
stringBuilder.setSpan(sizeSpan, 0, charSource.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
appendRelacement(builder, stringBuilder);
} finally {
continue;
}
}
return appendTail(builder);
}
private void appendRelacement(SpannableStringBuilder builder) {
builder.append(mSource.subSequence(mAppendPosition, mMatcher.start()));
CharSequence replacement = mIsSpannable
? copyCharSequenceWithSpans(mReplacement)
: mReplacement;
builder.append(replacement);
mAppendPosition = mMatcher.end();
}
private void appendRelacement(SpannableStringBuilder builder,CharSequence tempReplace) {
builder.append(mSource.subSequence(mAppendPosition, mMatcher.start()));
builder.append(tempReplace);
mAppendPosition = mMatcher.end();
}
private CharSequence copyCharSequenceWithSpans(CharSequence string) {
Parcel parcel = Parcel.obtain();
try {
TextUtils.writeToParcel(string, parcel, 0);
parcel.setDataPosition(0);
return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
} finally {
parcel.recycle();
}
}
private CharSequence appendTail(SpannableStringBuilder builder) {
builder.append(mSource.subSequence(mAppendPosition, mSource.length()));
return builder;
}
}