文字格式化-----String.format()
Android官方推荐TextView在设置内容的时候应该通过String文件来设置内容,而通过String文件获取内容,如:
getResources().getString(R.string.tv_content,"内容1","内容2")
实际上是通过String.Format( )(注:java中的方法)格式化文字,所以这里记录下String.Format( )格式化主要用到的几个点,
占位符说明
占位符完整格式为: %[index$][标识]*[最小宽度][.精度]转换符 。
针对不同数据类型的格式化,占位符的格式将有所裁剪。
% ,占位符的其实字符,若要在占位符内部使用%,则需要写成 %% 。
[index$] ,位置索引从1开始计算,用于指定对索引相应的实参进行格式化并替换掉该占位符。
[标识] ,用于增强格式化能力,可同时使用多个 [标识] ,但某些标识是不能同时使用的。
[最小宽度] ,用于设置格式化后的字符串最小长度,若使用 [最小宽度] 而无设置 [标识] ,那么当字符串长度小于最小宽度时,则以左边补空格的方式凑够最小宽度。
[.精度] ,对于浮点数类型格式化使用,设置保留小数点后多少位。
转换符 ,用于指定格式化的样式,和限制对应入参的数据类型。
常用的转换符说明:
%a 浮点数 (除了BigDecimal) 浮点数的十六进制输出
%b 任何类型 如果为非空则为“true”,为空则为“false”
%c 字符 Unicode字符
%d 证书(包括byte, short, int, long, bigint) 十进制整数
%e 浮点数 科学计数的十进制数
%f 浮点数 十进制数
%g 浮点数 十进制数,根据值和精度可能以科学计数法显示
%h 任何类型 通过hashCode()方法输出的16进制数
%n 无 平台相关的换行符
%o 整数(包括byte, short, int, long, bigint) 八进制数
%s 任何类型 字符串
%t 日期/时间 (包含long, Calendar, Date 和TemporalAccessor) %t是日期/时间转换的前缀。后面还需要跟其他的标识,请参考下面的日期/时间转换。
%x 整数(包含byte, short, int, long, bigint) 十六进制字符串
常见的空格占位符(转)
== 普通的英文半角空格
== == == no-break space (普通的英文半角空格但不换行)
== 中文全角空格 (一个中文宽度)
== == en空格 (半个中文宽度)
== == em空格 (一个中文宽度)
== 四分之一em空格 (四分之一中文宽度)
相比平时的空格( ),nbsp拥有不间断(non-breaking)特性。即连续的nbsp会在同一行内显示。即使有100个连续的nbsp,浏览器也不会把它们拆成两行
加载Html
常见支持的html标签
<b> 表示粗体文本。
<i> 表示斜体文本。
<u> 表示 下划线 文本
TextView是可以加载html的不过需要一些转换,如下
String string = "<a><u>你好啊</u></a>";
Spanned spanned = Html.fromHtml(string);
textView.setText(spanned);
如果要是在资源文件String中的话需要注意2点
1,在资源文件中所有的 < 都要用 <
替代,
在上面的String string = "<a><u>你好啊</u></a>"; 在资源文件中应该这样表示
<string name="text_content"><a><u>你好啊</u></a></string>
2,在给TextView设置文字的时候还要用 html转一下否则无法 html标签不起作用 因为:String.format(String, Object…) 方法会去除字符串中的所有样式信息
所以在资源文件中写html的方法如下
<string name="text_content"><a><u>你好啊</u></a></string>
textView.setText(Html.fromHtml(getResources().getString(R.string.text_content)));
TextView富文本
TextView富文本即是修改TextView的样式,Android中提供修改TextView的样式的类都在android.text.style包中,而设置富文本的方式是通过SpannableString.setSpan()或者是SpannableStringBuilder.setSpan()方法给文字设置样式,最后再将SpannableString或者SpannableStringBuilder设置进TextView中
方法说明,SpannableString,SpannableStringBuilder的setSpan方法说明
void setSpan(Object what, int start, int end, int flags)
参数
what 要设置的字体样式
start样式的开始位置
end 样式的结束位置
flags 是否包含开始位置,结束位置
flags的状态(Spanned接口中的值)
SPAN_EXCLUSIVE_EXCLUSIVE 不包括起点和终点
SPAN_EXCLUSIVE_INCLUSIVE 包括终点但是不包括起点
SPAN_INCLUSIVE_EXCLUSIVE 包括起点但是不包括终点
SPAN_INCLUSIVE_INCLUSIVE 包括起点和终点
EXCLUSIVE 排除的意思
INCLUSIVE 包含的意思 这样是不是好记忆了
字体样式的类主要有:
AbsoluteSizeSpan 设置字体大小 按照绝对大小
使用:
xml:
<TextView
android:id="@+id/tv_content"
android:textSize="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
String str = "我是测试文本,我是测试文本我是测试文本我是测试文本我是测试文本我是测试" +
"本我是测试文本我是测试文本我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
spannableString.setSpan(new AbsoluteSizeSpan(10, true), 0, 4, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
spannableString.setSpan(new AbsoluteSizeSpan(30, true), 4, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(spannableString);
效果:
AbsoluteSizeSpan(int size)
设置文本大小 单位px
AbsoluteSizeSpan(int size, boolean dip)
设置文本大小 是否是dp 不是dp则单位是px 是dp单位是dp
RelativeSizeSpan 设置字体相对大小,相对没有设置RelativeSizeSpan的字体大小 比如1.5f是其他字体大小的1.5倍##
使用
`String str = "我是测试文本,我是测试文本我是测试文本我是测试文本我是测试文本我是测试" +
"本我是测试文本我是测试文本我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
spannableString.setSpan(new RelativeSizeSpan(0.5f),0,10,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
spannableString.setSpan(new RelativeSizeSpan(1.5f),11,20,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(spannableString);`
效果:
注意:
RelativeSizeSpan(float proportion) proportion是相对没有设置RelativeSizeSpan的字体的相对大小,1.5f是其大小的1.5倍
AlignmentSpan.Standard 改变文字的对齐方式
使用
String str = "我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
AlignmentSpan.Standard alignmentSpan = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE);
spannableString.setSpan(alignmentSpan, 0, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
效果是将对齐方式改为之前对齐方式对立面 比如中文是左对齐,代码运行后是右对齐(前提是TextView的大小要大于文字的大小,否则看不出对齐方式)
构造函数
AlignmentSpan.Standard(Layout.Alignment align)
填入对齐方式
ALIGN_NORMAL,
ALIGN_OPPOSITE,//对立
ALIGN_CENTER, //居中
/** @hide */
ALIGN_LEFT,
/** @hide */
ALIGN_RIGHT,
PS:说明感觉这个没什么用,因为我们完全可以通过gravity熟悉来设置对齐方式
BackgroundColorSpan 改变字体的背景颜色
使用
String str = "我是测试文本,我是测试文本我是测试文本我是测试文本我是测试文本我是测试" +
"本我是测试文本我是测试文本我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.parseColor("#FF0000"));
spannableString.setSpan(backgroundColorSpan, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
效果:
构造函数:
BackgroundColorSpan(int color)
直接传入要显示背景颜色即可
ForegroundColorSpan 改变字体的颜色##
使用:
` String str = "我是测试文本,我是测试文本我是测试文本我是测试文本我是测试文本我是测试" +
"本我是测试文本我是测试文本我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
spannableString.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.red)),2,12,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);`
效果
ClickableSpan 实现点击TextView不同的地方实现不同的点击效果 并且可以设置可点击字体颜色
这个一般用来实现话题 @人 之类的社交产品中 如微博 QQ等
使用,说明查找 “#…#” 然后点击 "#…#"弹出相应的文字
String str = "删库跑路,是对程序员的一种调侃,#我是话题1#多用于程序员压力大的一种自我调侃或者#我是话题2#是开玩笑的话。" +
"实际上很少有删库跑路的现象出现,即便有类似情况,最后也都被法律制裁。近日有一家公司因为员工的“锁库跑路”,导致公司最终被迫解散," +
"老板身负重债无奈打工#我是话题3#";
SpannableString spannableString = new SpannableString(str);
String pa = "#[^#]*#";
Pattern pattern = Pattern.compile(pa);
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
String group = matcher.group();
int start = matcher.start();
int end = start + group.length();
spannableString.setSpan(new CustomClickableSpan(group), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(spannableString);
//设置文字高亮颜色,去除点击后的背景颜色
textView.setHighlightColor(getResources().getColor(R.color.translate));
ClickableSpan类
class CustomClickableSpan extends ClickableSpan {
private String text;
public CustomClickableSpan(String text) {
this.text = text;
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
//设置是否有下划线
ds.setLinearText(false);
//设置点击文字的颜色
ds.setColor(getResources().getColor(R.color.red));
}
@Override
public void onClick(@NonNull View widget) {
AppCompatTextView textView = (AppCompatTextView) widget;
Toast.makeText(Main2Activity.this, "点击了" + text, Toast.LENGTH_SHORT).show();
}
}
说明:
- ClickableSpan是个抽象类 需要我们自己集成并且实现其onClick方法,传入的参数widget是整个TextView,注意是整个TextView对象
- 当我们设置ClickableSpan之后还需要设置MovementMethod,否则点击无效,即是
textView.setMovementMethod(LinkMovementMethod.getInstance());
- 点击后可能会出现背景色,这个背景色是文字高亮颜色需要我们手动设置其颜色为透明色(或者你想要的其他颜色),即是
textView.setHighlightColor(getResources().getColor(R.color.translate));
效果如下:暂时不上gif了 麻烦
DrawableMarginSpan
在文字前面添加一个Drawable 文字在该drawable的右侧,很鸡肋的一个功能类
使用:
String str = "我是测试文本,我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
spannableString.setSpan(new DrawableMarginSpan(getResources().getDrawable(R.mipmap.icon),100),0,str.length()-1,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setBackgroundColor(getResources().getColor(R.color.red));
textView.setText(spannableString);
说明:
DrawableMarginSpan有两个构造函数, DrawableMarginSpan(Drawable drawable)
参数是要设置的drawable DrawableMarginSpan(Drawable drawable, int pad)
参数1是要设置的drawable 参数2是图片和文字之间的间距
效果如下:
DynamicDrawableSpan 实现在文本中添加图片资源的抽象类##
注意这是一个抽象类,如果我们要使用它,需要实现它的抽象方法abstract Drawable getDrawable()
用来提供可绘制的drawable资源,我们简单使用的话,可以这样使用
class MyDynamicDrawableSpan extends DynamicDrawableSpan {
private final Context mContext;
private final int mResourceId;
public MyDynamicDrawableSpan(Context context, @DrawableRes int resourceId) {
mContext = context;
mResourceId = resourceId;
}
@Override
public Drawable getDrawable() {
Drawable drawable = mContext.getDrawable(mResourceId);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
return drawable;
}
}
但是官方给我们提供了一个实现子类ImageSpan,我们可以直接使用它
ImageSpan 实现文本中添加图片,DynamicDrawableSpan的实现类
使用:我们在一段文字的不同位置插入图片,这是在4个位置插入4张图片
` String str = "我是测试文本,我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
spannableString.setSpan(new ImageSpan(this,R.mipmap.icon,DynamicDrawableSpan.ALIGN_BOTTOM),2,5,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ImageSpan(this,R.mipmap.icon,DynamicDrawableSpan.ALIGN_BASELINE),10,11,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ImageSpan(this,R.mipmap.icon,DynamicDrawableSpan.ALIGN_BASELINE),30,31,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ImageSpan(this,R.mipmap.icon,DynamicDrawableSpan.ALIGN_BASELINE),18,19,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);`
效果图如下:
注意:
- 如果我们想要控制图片的大小 我们可以重写 getDrawable方法 压缩bitmap
- 如果我们需要更改图片和文字的对齐方式,可以重写 draw 方法 进而更改图片的对齐方式
- 我们需要插入多少图片就要new出来多少个ImageSpan,ImageSpan不可复用,复用后只能显示最后设置的位置
- 图片插入的位置是在start之后
TextAppearanceSpan 设置文本样式(字体大小,颜色等等,该样式要通过style来设置)
使用
`
<style name="text1" parent="Widget.AppCompat.AutoCompleteTextView">
<item name="android:textSize">15sp</item>
<item name="android:textColor">#f00</item>
</style>
<style name="text2" parent="Widget.AppCompat.AutoCompleteTextView">
<item name="android:textSize">30sp</item>
<item name="android:textColor">#00f</item>
</style>
String str = "我是测试文本,我是测试文本我是测试文本我是测试文本我是测试文本我是测试" +
"本我是测试文本我是测试文本我是测试文本";
TextView textView = findViewById(R.id.tv_content);
SpannableString spannableString = new SpannableString(str);
spannableString.setSpan(new TextAppearanceSpan(this,R.style.text1),0,10,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
spannableString.setSpan(new TextAppearanceSpan(this,R.style.text2),11,20,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(spannableString);`
效果: