TextView
富文本显示主要有两种方式:
SpannableString
类html
下面介绍这两种方式实现
SpannableString
类StyleSpan
)[粗体、斜体等]TypefaceSpan
)ForegroundColorSpan
)AbsoluteSizeSpan
)RelativeSizeSpan
)ImageSpan
)ClickableSpan
)URLSpan
)BackgroundColorSpan
)UnderlineSpan
)StrikethroughSpan
)RasterizerSpan
)MaskFilterSpan
)SubscriptSpan
)SuperscriptSpan
)ScaleXSpan
)TextAppearanceSpan
)setSpan()
void setSpan (Object what, int start, int end, int flags)
参数说明
参数 | 类型 | 说明 |
---|---|---|
what |
Object |
样式 |
start |
int |
样式开始的字符索引 |
end |
int |
样式结束的字符索引 |
flags |
int |
新插入字符的设置 |
flags
值
取值 | 说明 |
---|---|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE |
前后都不包括 |
Spanned.SPAN_EXCLUSIVE_INCLUSIVE |
前面不包括,后面包括 |
Spanned.SPAN_INCLUSIVE_EXCLUSIVE |
前面包括,后面不包括 |
Spanned.SPAN_INCLUSIVE_INCLUSIVE |
前后都包括 |
举例说明各参数:
StyleSpan
) // 把字体改为粗体 Typeface.BOLD
textSpanned.setSpan(new StyleSpan(Typeface.BOLD), 0, 10, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
Typeface.*
参数 | 说明 |
---|---|
Typeface.NORMAL |
默认字体 |
Typeface.BOLD |
粗体 |
Typeface.ITALIC |
斜体 |
Typeface.BOLD_ITALIC |
粗斜体 |
TypefaceSpan
)作用: 修改文字字体格式(不同于StyleSpan
),
使用:
使用系统自带
系统自带monospace
、serif
、sans-serif
SpannableString sansSerifText = new SpannableString("这是sans-serif字体\n");
TypefaceSpan sansSerif = new TypefaceSpan("sans-serif");
sansSerifText.setSpan(sansSerif, 0, sansSerifText.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
使用自定义字体
src\main\assets\
下Typeface
public class TypefaceUtil {
private static final HashMap<String, Typeface> sCachedFonts = new HashMap<String, Typeface>();
private static final String PREFIX_ASSET = "asset:";
private TypefaceUtil() {
}
/**
* @param familyName if start with 'asset:' prefix, then load font from asset folder.
*/
public static Typeface load(Context context, String familyName, int style) {
if (familyName != null && familyName.startsWith(PREFIX_ASSET)) {
synchronized (sCachedFonts) {
try {
if (!sCachedFonts.containsKey(familyName)) {
final Typeface typeface = Typeface.createFromAsset(context.getAssets(), familyName.substring(PREFIX_ASSET.length()));
sCachedFonts.put(familyName, typeface);
return typeface;
}
} catch (Exception e) {
e.printStackTrace();
return Typeface.DEFAULT;
}
return sCachedFonts.get(familyName);
}
}
return Typeface.create(familyName, style);
}
}
MetricAffectingSpan
类static class CustomTypefaceSpan extends MetricAffectingSpan {
private final Typeface typeface;
CustomTypefaceSpan(final Typeface typeface) {
this.typeface = typeface;
}
@Override
public void updateDrawState(final TextPaint drawState) {
apply(drawState);
}
@Override
public void updateMeasureState(final TextPaint paint) {
apply(paint);
}
private void apply(final Paint paint) {
final Typeface oldTypeface = paint.getTypeface();
final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0;
final int fakeStyle = oldStyle & ~typeface.getStyle();
if ((fakeStyle & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fakeStyle & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(typeface);
}
}
SpannableString
SpannableString customText0 = new SpannableString("这是自定义字体1\n");
CustomTypefaceSpan customTypefaceSpan0 = new CustomTypefaceSpan(TypefaceUtil.load(this, "asset:text.ttf", 0));
customText0.setSpan(customTypefaceSpan0, 0, customText0.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ForegroundColorSpan
) SpannableString spannableString = new SpannableString("设置文本颜色");
spannableString.setSpan(new ForegroundColorSpan(Color.BLUE), 0, spannableString .length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
textView.setText(spannableString );
AbsoluteSizeSpan
、RelativeSizeSpan
)AbsoluteSizeSpan
SpannableString spannableString = new SpannableString("使用绝对大小设置文字尺寸");
spannableString.setSpan(new AbsoluteSizeSpan(40), 0,2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
SpannableString spannableString = new SpannableString("使用相对大小设置文字尺寸");
spannableString.setSpan(new RelativeSizeSpan(1.5F), 0, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
ImageSpan
) Drawable drawable = getDrawable(R.mipmap.icon);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
ImageSpan imageSpan = new ImageSpan(drawable);
sp.setSpan(imageSpan, 0, 1, ImageSpan.ALIGN_BASELINE);
public class CenterAlignImageSpan extends ImageSpan {
public CenterAlignImageSpan(Drawable drawable) {
super(drawable);
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
Drawable b = getDrawable();
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
//计算y方向的位移
int transY = (y + fm.descent + y + fm.ascent) / 2 - b.getBounds().bottom / 2;
canvas.save();
//绘制图片位移一段距离
canvas.translate(x, transY);
b.draw(canvas);
canvas.restore();
}
}
//使用
CenterAlignImageSpan imageSpan1 = new CenterAlignImageSpan(drawable);
sp.setSpan(imageSpan1,0, 1, ImageSpan.ALIGN_CENTER);
ClickableSpan
) textView.setTextIsSelectable(true);
//方法重新设置文字点击
textView.setMovementMethod(LinkMovementMethod.getInstance());
//方法重新设置文字背景为透明色。
textView.setHighlightColor(getResources().getColor(android.R.color.darker_gray));
String text = "这句话中有两个地方可以点击,\n第一个地方是百度,\n另一个地方在这四个字";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new Clickable(firstClickListener), text.indexOf("百度"), text.indexOf(",\n另"), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new Clickable(secondClickListener), text.indexOf("这四个字"), text.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
private View.OnClickListener firstClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse(url);
Context context = v.getContext();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
context.startActivity(intent);
}
};
private View.OnClickListener secondClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ClickableActivity.this, "第二个点击事件", Toast.LENGTH_SHORT).show();
}
};
static class Clickable extends ClickableSpan {
View.OnClickListener listener;
Clickable(View.OnClickListener listener) {
this.listener = listener;
}
@Override
public void onClick(@NonNull View v) {
listener.onClick(v);
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(0xFF0474E5);//设置文字颜色
ds.setUnderlineText(false); //去除超链接的下划线
ds.clearShadowLayer();
}
}
URLSpan
) textView.setTextIsSelectable(true);
//方法重新设置文字点击
textView.setMovementMethod(LinkMovementMethod.getInstance());
//方法重新设置文字背景为透明色。
textView.setHighlightColor(getResources().getColor(android.R.color.darker_gray));
SpannableString ss = new SpannableString("百度一下");
ss.setSpan(new URLSpan("http://www.baidu.com"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
BackgroundColorSpan
) String text = "这个字背景是蓝色的,\n这个字背景是红色的";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new BackgroundColorSpan(0xff00ddff), 6, 8, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
spannableString.setSpan(new BackgroundColorSpan(0xffcc0000), text.length() - 3, text.length() - 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(spannableString);
UnderlineSpan
) String text = "下面这句话是重点,\n记得划线";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new UnderlineSpan(), text.length() - 4, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString );
StrikethroughSpan
) String text = "如果想注释某些不需要的文字,\n可以使用中划线";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new StrikethroughSpan(), text.length() - 3, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString );
MaskFilterSpan
) SpannableString spannableString = new SpannableString("修饰效果 NORMAL");
spannableString.setSpan(new MaskFilterSpan(new BlurMaskFilter(4, BlurMaskFilter.Blur.SOLID)), 0, 4,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString );
SubscriptSpan
) String text = "下标:通常在数学公式中使用,例如:\nx1-x2-2=0";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new SubscriptSpan(), text.indexOf("1"), text.indexOf("1") + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new SubscriptSpan(), text.indexOf("2"), text.indexOf("2") + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString );
SuperscriptSpan
) String text = "上标标:通常在数学公式中使用,例如:\nx2-x1-2=0";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new SuperscriptSpan(), text.indexOf("1"), text.indexOf("1") + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new SuperscriptSpan(), text.indexOf("2"), text.indexOf("2") + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString );
ScaleXSpan
) String text = "基于x轴进行缩放";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new ScaleXSpan(1.6F), text.length() - 2, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString );
TextAppearanceSpan
)<resources>
<style name="style_black">
- "android:textSize"
>30sp
- "android:textColor">@android:color/black
- "android:textStyle">bold
style>
resources>
String text = "文本外貌是什么样式";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new TextAppearanceSpan(this, R.style.style_black), text.length() - 2, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString );
SpannableStringBuilder
类String
、SpannableString
等,方便操作,提升性能。 SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
//拼接String 类型
String string = "这是一个String字符串\n";
spannableStringBuilder.append(string);
//拼接SpannableString
SpannableString spannableString = new SpannableString("这是要给SpannableString字符串");
spannableString.setSpan(new ForegroundColorSpan(0x80323232), 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
spannableStringBuilder.append(spannableString);
textView.setText(spannableStringBuilder);
Html.fromHtml(String)
方法可以把html格式解析转换成Spanned就可以使TextView解析显示不同的样式。 String string = "这是正常文字 html 设置文字颜色、大小"
;
textView.setText(Html.fromHtml(string));