Android TextView 富文本 SpannableString 与 SpannableStringBuilder
单个TextView 要实现复杂的富文本效果,可借助SpannableString实现。
主要实现方法 SpannableString.setSpan(Object what, int start, int end, int flags)
what 参数,控制文本效果,主要有以下类型
- BackgroundColorSpan 背景色
- ClickableSpan 点击事件
- ForegroundColorSpan 文本颜色(前景色)
- MaskFilterSpan 修饰效果,如模糊(BlurMaskFilter)浮雕(EmbossMaskFilter)
- MetricAffectingSpan 父类,一般不用
- RasterizerSpan 光栅效果
- StrikethroughSpan 删除线
- SuggestionSpan 占位符
- UnderlineSpan 下划线
- AbsoluteSizeSpan 文本字体,绝对大小
- DynamicDrawableSpan 设置图片,基于文本基线或底部对齐
- ImageSpan 图片
- RelativeSizeSpan 文本字体,相对大小
- ReplacementSpan 父类,一般不用
- ScaleXSpan 基于x轴缩放
- StyleSpan 字体样式:粗体、斜体等
- SubscriptSpan 下标(数学公式会用到)
- SuperscriptSpan 上标(数学公式会用到)
- TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)
- TypefaceSpan 文本字体
- URLSpan 文本超链接
start、end 参数
start 指定span开始位置。包括该位置。
end 指定span结束位置,不包括该位置。
flags 参数,指定前后文本会不会用span样式
- Spannable.SPAN_INCLUSIVE_EXCLUSIVE 前面用,后面不用
- Spannable.SPAN_INCLUSIVE_INCLUSIVE 前后都会使用span样式
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE 前后都不会使用span样式
- Spannable.SPAN_EXCLUSIVE_INCLUSIVE 前面不用,后面用
基本使用效果
- 背景色
// 背景色
private void setBackgroundColor() {
SpannableString spannableString = new SpannableString("测试用的文本修改字体背景颜色");
//BackgroundColorSpan backSpan = new BackgroundColorSpan(Color.parseColor("#0000ff"));
BackgroundColorSpan backSpan = new BackgroundColorSpan(Color.RED);
//BackgroundColorSpan backSpan = new BackgroundColorSpan(CommonUtils.getColor(TestActivity.this, R.color.colorAccent));
spannableString.setSpan(backSpan, 0, 5, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
}
- 前景色
// 前景色
private void setForegroundColor() {
SpannableString spannableString = new SpannableString("测试用的文本修改字体前景颜色");
//ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#ff0000"));
//ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.BLUE);
ForegroundColorSpan colorSpan = new ForegroundColorSpan(CommonUtils.getColor(TestActivity.this, R.color.colorAccent));
spannableString.setSpan(colorSpan, 0, 5, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv02.setText(spannableString);
}
- 模糊
// 修饰效果-模糊
private void setBlurMaskFilter() {
// 注意:使用 MaskFilterSpan 修饰效果,需要关闭硬件加速,不然没有效果出来。
// 在AndroidManifest.xml中对应的activity设置android:hardwareAccelerated="false"
// 参看:https://stackoverflow.com/questions/46089196/how-to-using-android-spannablestring-and-maskfilterspan-to-blur-some-text-from-t
SpannableString spannableString = new SpannableString("测试用的文本修饰效果之模糊测试");
MaskFilterSpan blurSpan0 = new MaskFilterSpan(new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL));
MaskFilterSpan blurSpan4 = new MaskFilterSpan(new BlurMaskFilter(20, BlurMaskFilter.Blur.SOLID));
MaskFilterSpan blurSpan8 = new MaskFilterSpan(new BlurMaskFilter(20, BlurMaskFilter.Blur.OUTER));
MaskFilterSpan blurSpan12 = new MaskFilterSpan(new BlurMaskFilter(20, BlurMaskFilter.Blur.INNER));
spannableString.setSpan(blurSpan0, 0, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
spannableString.setSpan(blurSpan4, 4, 6, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
spannableString.setSpan(blurSpan8, 8, 10, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
spannableString.setSpan(blurSpan12, 12, 14, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
}
- 删除线
// 删除线
private void setStrikethroughSpan() {
SpannableString spannableString = new SpannableString("测试用的文本加上删除线");
StrikethroughSpan backSpan = new StrikethroughSpan();
spannableString.setSpan(backSpan, 0, 5, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
}
- 下划线
// 下划线
private void setUnderlineSpan() {
SpannableString spannableString = new SpannableString("测试用的文本加上下划线");
UnderlineSpan span = new UnderlineSpan();
spannableString.setSpan(span, 0, 5, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
}
- 字体大小(绝对大小)
// 字体大小(相对大小)
private void setRelativeSizeSpan() {
SpannableString spannableString = new SpannableString("测试用的文本图片字体大小(相对大小)");
RelativeSizeSpan span = new RelativeSizeSpan(1.5f);
spannableString.setSpan(span, 0, 5, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
}
- 基于x轴缩放
// 基于x轴缩放
private void setScaleXSpan() {
SpannableString spannableString = new SpannableString("测试用的文本基于x轴缩放");
ScaleXSpan span = new ScaleXSpan(0.5f);
spannableString.setSpan(span, 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
SpannableString spannableString2 = new SpannableString("测试用的文本基于x轴缩放");
for (int i = 0; i < spannableString2.length(); i++) {
float proportion = (float) (0.5f + (0.1 * i));
spannableString2.setSpan(new ScaleXSpan(proportion), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
tv02.setText(spannableString2);
}
- 加粗斜体
// 加粗斜体
private void setStyleSpan() {
SpannableString spannableString = new SpannableString("测试加粗测试斜体测试加粗斜体");
// 加粗
StyleSpan span = new StyleSpan(Typeface.BOLD);
spannableString.setSpan(span, 2, 4, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
// 斜体
StyleSpan span2 = new StyleSpan(Typeface.ITALIC);
spannableString.setSpan(span2, 6, 8, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
// 加粗斜体
StyleSpan span3 = new StyleSpan(Typeface.BOLD_ITALIC);
spannableString.setSpan(span3, 10, 14, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
}
- 上标下标(数学公式会用到)
// 上标下标(数学公式会用到)
private void setSubscriptSpan() {
SpannableString spannableString = new SpannableString("测试用的文本2018");
SuperscriptSpan span = new SuperscriptSpan();
spannableString.setSpan(span, 6, 10, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
SpannableString spannableString2 = new SpannableString("测试用的文本2018");
SubscriptSpan span2 = new SubscriptSpan();
spannableString2.setSpan(span2, 6, 10, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv02.setText(spannableString2);
}
- 文本外貌(包括字体、大小、样式和颜色)
// 文本外貌(包括字体、大小、样式和颜色)
private void setTextAppearanceSpan() {
SpannableString sstr = new SpannableString("测试文本修改字体修改大小修改样式修改颜色");
ColorStateList csl = getResources().getColorStateList(R.color.red);
TextAppearanceSpan span = new TextAppearanceSpan("default", android.graphics.Typeface.BOLD, 20, csl, null);
sstr.setSpan(span, 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv01.setText(sstr);
}
- 设置字体
// 设置字体
private void setTypefaceSpan() {
SpannableString spannableString = new SpannableString("测试用的文本");
// "monospace", "serif", and "sans-serif".
TypefaceSpan span = new TypefaceSpan("serif");
spannableString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
}
- 设置链接
// 设置链接
private void setURLSpan() {
SpannableString spannableString = new SpannableString("测试用的文本这是链接地址");
spannableString.setSpan(new URLSpan("https://baidu.com"), 0, 5, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
// 执行动作需要设置MovementMethod
tv01.setMovementMethod(LinkMovementMethod.getInstance());
}
- 点击事件
// 设置点击事件
private void setClickableSpan() {
SpannableString spannableString = new SpannableString("测试用的文本点击事件");
ClickableSpan span = new ClickableSpan() {
@Override
public void onClick(View widget) {
showToast("点一点");
}
};
spannableString.setSpan(span, spannableString.length() - 4, spannableString.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
tv01.setText(spannableString);
// 执行动作需要设置MovementMethod
tv01.setMovementMethod(LinkMovementMethod.getInstance());
}
参看:
https://blog.csdn.net/fengyuzhengfan/article/details/38459299
https://www.jianshu.com/p/f004300c6920