通过Spannable对象我们可以设置textview的各种样式
用法
setSpan(Object what, int start, int end, int flags)
1. 第一个参数
what 意思
AbsoluteSizeSpan 指定文字大小
TypefaceSpan 可以设置不同的字体
AlignmentSpan.Standard 标准文本对齐
BackgroundColorSpan 文本背景颜色
ForegroundColorSpan 文字字体颜色
LeadingMarginSpan 文本缩进
TabStopSpan 制表位偏移样式
TextAppearanceSpan 使用style文件来定义文本样式
RelativeSizeSpan 对于文本设定的大小的相对比例
ScaleXSpan 将字体按比例进行横向缩放
URLSpan 可以打开一个链接
StyleSpan 正常、粗体、斜体和同时加粗倾斜四种样式
StrikethroughSpan 删除线样式
QuoteSpan 在文本左侧添加一条表示引用的竖线
UnderlineSpan 给一段文字加上下划线
SubscriptSpan 脚注样式,比如化学式的常见写法
SuperscriptSpan 上标样式,比如数学上的次方运算
BulletSpan 文本着重样式,类似于HTML中的标签的圆点效果
DrawableMarginSpan/IconMarginSpan 图片+Margin样式
ImageSpan 图片样式,主要用于在文本中插入图片 聊天中的emoji表情显示用的就是这个
MaskFilterSpan 文本滤镜 目前只有模糊效果和浮雕效果
RasterizerSpan 光栅化
2. 第四个参数
Flags 意思 符号
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 不包含start和end两端所在的端点 (a,b)
Spanned.SPAN_EXCLUSIVE_INCLUSIVE 不包含start端,但包含end所在的端点 (a,b]
Spanned.SPAN_INCLUSIVE_EXCLUSIVE 包含start端,但不包含end所在的端点 [a,b)
Spanned.SPAN_INCLUSIVE_INCLUSIVE 包含start和end两端所在的端点 [a,b]
3. 自定义圆角背景
package com.ypf.study.myroom;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.style.ReplacementSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class RoundBackgroundColorSpan extends ReplacementSpan {
private int bgColor;
private int textColor;
public RoundBackgroundColorSpan(int bgColor, int textColor) {
super();
this.bgColor = bgColor;
this.textColor = textColor;
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
int originalColor = paint.getColor();
paint.setColor(this.bgColor);
//画圆角矩形背景
canvas.drawRoundRect(new RectF(x,
top + 1,
x + ((int) paint.measureText(text, start, end) + dp2px(10)),
bottom - 1),
dp2px(4),
dp2px(4),
paint);
paint.setColor(this.textColor);
//画文字,两边各增加8dp
canvas.drawText(text, start, end, x + dp2px(5), y, paint);
//将paint复原
paint.setColor(originalColor);
}
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {
//设置宽度为文字宽度加16dp
return ((int) paint.measureText(text, start, end) + dp2px(10));
}
private int dp2px(int dp) {
return 5 * dp;
}
}
4. 简单实用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.test_span);
String text = " # 影综创作者激励计划 # 我的快乐源泉 # 追剧 # 聚会开心时刻 # 青春不毕业 闺蜜模范,谁身边不想要一个这样的姐妹";
SpannableStringBuilder builder = new SpannableStringBuilder(text);
Matcher m = LABEL_PATTERN.matcher(builder);
while (m.find()) {
int start = m.start();
int end = m.end();
if (end - start == 1) {
continue;
}
builder.setSpan(new AbsoluteSizeSpan(15), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
builder = new SpannableStringBuilder(builder);
m = LABEL_PATTERN.matcher(builder);
while (m.find()) {
int start = m.start();
int end = m.end();
if (end - start == 1) {
continue;
}
builder.setSpan(new RoundBackgroundColorSpan(Color.GRAY, Color.BLACK), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
textView.setText(builder);
}
效果
5. bug场景
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.test_span);
String text = " # 影综创作者激励计划 # 我的快乐源泉 # 追剧 # 聚会开心时刻 # 青春不毕业 闺蜜模范,谁身边不想要一个这样的姐妹 # 青春不毕业 ";
SpannableStringBuilder builder = new SpannableStringBuilder(text);
Matcher m = LABEL_PATTERN.matcher(builder);
while (m.find()) {
int start = m.start();
int end = m.end();
if (end - start <= 1) {
continue;
}
builder.setSpan(new AbsoluteSizeSpan(dp2px(4)), start,
start + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
builder.setSpan(new AbsoluteSizeSpan(dp2px(4)),
start + 2, start + 3, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
builder.setSpan(new AbsoluteSizeSpan(dp2px(4)), end - 1, end,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
textView.setText(builder);
m = LABEL_PATTERN.matcher(builder);
while (m.find()) {
int start = m.start();
int end = m.end();
if (end - start <= 1) {
continue;
}
builder.setSpan(new RoundBackgroundColorSpan(Color.GRAY, Color.BLACK), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
textView.setText(builder);
}
private int dp2px(int dp) {
return 5 * dp;
}
效果
修复方案