使用SpannableStringBuilder注意事项 xx 2023年10月27日 需求中有一行文字显示的大小、颜色、下划线、加粗等不同,可以用几个TextView实现,也可以用SpannableStringBuilder在一个TextView上实现,还可以在string的文件中用H5的语法写。
后两种的差别主要在点击事件上,用H5的语法没法对一个字符串中的几个字设置点击事件。
使用时把多个字符串用append()方法拼接上,设置需要用到的Span。
设置Span时要注意按照顺序 设置颜色、点击事件时Span对象不能复用,用几个就要创建几个 对ClickableSpan默认有下划线,可以重写updateDrawState方法去掉 用ClickableSpan时,除了用setText,还要用lawAndPrivacyTv.setMovementMethod(LinkMovementMethod.getInstance())否则点击事件不生效 另,重写的updateDrawState方法里也可以设置默认颜色(setColor) Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
:前后都不包括,即在指定范围的前面和后面插入新字符都不会应用新样式
Spannable.SPAN_EXCLUSIVE_INCLUSIVE
:前面不包括,后面包括。即仅在范围字符的后面插入新字符时会应用新样式
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
:前面包括,后面不包括。
Spannable.SPAN_INCLUSIVE_INCLUSIVE
:前后都包括。
源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private void initLawAndPrivacyTv () {
int position = 0 ;
String agree = Utils . getString ( R . string . text_agree );
String privacy = Utils . getString ( R . string . privacy_policy );
String and = Utils . getString ( R . string . text_and );
String law = Utils . getString ( R . string . law_policy );
ForegroundColorSpan agreeBlackSpan = new ForegroundColorSpan ( Color . BLACK );
ForegroundColorSpan andBlackSpan = new ForegroundColorSpan ( Color . BLACK );
ForegroundColorSpan privacyBlueSpan = new ForegroundColorSpan ( Utils . getColor ( R . color . color_3091F2 ));
ForegroundColorSpan lawBlueSpan = new ForegroundColorSpan ( Utils . getColor ( R . color . color_3091F2 ));
ClickableSpan privacyClickableSpan = new ClickableSpan () {
@Override
public void onClick ( @NonNull View widget ) {
jumpToPrivacyPolicy ();
}
@Override
public void updateDrawState ( @NonNull TextPaint textPaint ) {
super . updateDrawState ( textPaint );
textPaint . setUnderlineText ( false );
}
};
ClickableSpan lawClickableSpan = new ClickableSpan () {
@Override
public void onClick ( @NonNull View widget ) {
JumpToLawPolicy ();
}
@Override
public void updateDrawState ( @NonNull TextPaint textPaint ) {
super . updateDrawState ( textPaint );
textPaint . setUnderlineText ( false );
}
};
SpannableStringBuilder stringBuilder = new SpannableStringBuilder ();
stringBuilder . append ( agree );
stringBuilder . setSpan ( agreeBlackSpan , 0 , stringBuilder . length (), Spanned . SPAN_EXCLUSIVE_EXCLUSIVE );
position += agree . length ();
stringBuilder . append ( law );
stringBuilder . setSpan ( lawBlueSpan , position , stringBuilder . length (), Spanned . SPAN_EXCLUSIVE_EXCLUSIVE );
stringBuilder . setSpan ( lawClickableSpan , position , stringBuilder . length (), Spanned . SPAN_EXCLUSIVE_EXCLUSIVE );
position += law . length ();
stringBuilder . append ( and );
stringBuilder . setSpan ( andBlackSpan , position , stringBuilder . length (), Spanned . SPAN_EXCLUSIVE_EXCLUSIVE );
position += and . length ();
stringBuilder . append ( privacy );
stringBuilder . setSpan ( privacyBlueSpan , position , stringBuilder . length (), Spanned . SPAN_EXCLUSIVE_EXCLUSIVE );
stringBuilder . setSpan ( privacyClickableSpan , position , stringBuilder . length (), Spanned . SPAN_EXCLUSIVE_EXCLUSIVE );
lawAndPrivacyTv . setText ( stringBuilder );
// 不设置点击事件不起作用
lawAndPrivacyTv . setMovementMethod ( LinkMovementMethod . getInstance ());
}
除了SpannableStringBuilder,还有个SpannableString,区别和String与StringBuilder的区别相同。
补充:
四种flag在按照顺序拼接文字时没有区别,区别在SpannableStringBuilder#insert
时,如下(x为增加的):
SPAN_INCLUSIVE_INCLUSIVE
SPAN_INCLUSIVE_EXCLUSIVE
SPAN_EXCLUSIVE_INCLUSIVE
SPAN_EXCLUSIVE_EXCLUSIVE
Java代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String myString = "01234" ;
int start = 1 ;
int end = 3 ;
int spanFlag = Spannable . SPAN_INCLUSIVE_INCLUSIVE ; // this is what is changing
// set the span
SpannableStringBuilder spannableString = new SpannableStringBuilder ( myString );
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan ( Color . RED );
spannableString . setSpan ( foregroundSpan , start , end , spanFlag );
// insert the text after the span has already been set
// (inserting at start index second so that end index doesn't get messed up)
spannableString . insert ( end , "x" );
spannableString . insert ( start , "x" );
textView . setText ( spannableString );
上篇:Toast异常:BadTokenException
下篇:你需要知道的inlcude标签属性