您的位置:首页 > 产品设计 > UI/UE

SpannableStringBuilder的setSpan方法使用需注意点!

2017-08-08 17:39 507 查看

以前偶然遇见一个问题,今天突然想起来了,机智的我赶紧贴过来以帮助遇见此问题尚未解决的小伙伴们


这个问题是关于SpannableStringBuilder类的setSpan方法的。

大家都知道setSpan方法在使用时需要传入四个参数:

public void setSpan(Object what, int start, int end, int flags) {
throw new RuntimeException("Stub!");
}


第一个参数:Object what。我们使用的时候传入一个CharacterStyle对象。

第二、三个参数很好理解,intstart,
int end。分别表示要把字符串中从start开始到end结束的位置设置成what样式的。当然,start是从0开始的,而修改样式的位置是[start,end),也就是说包含start位置但不包含end位置,这样就确保了实际修改的“子字符串”的长度是end - start。

第四个参数是intflags,表示要将字符串按照指定的flag进行修改。它定义在Spanner类中,我们常用到的有以下几种:

int SPAN_EXCLUSIVE_EXCLUSIVE = 33; //在Span前后输入的字符都不应用Span效果
int SPAN_EXCLUSIVE_INCLUSIVE = 34; //在Span前面输入的字符不应用Span效果,后面输入的字符应用Span效果
int SPAN_INCLUSIVE_EXCLUSIVE = 17; //在Span前面输入的字符应用Span效果,后面输入的字符不应用Span效果
int SPAN_INCLUSIVE_INCLUSIVE = 18; //在Span前后输入的字符都应用Span效果

下面着重说一下what参数。

我们可以把newForegroundColorSpan(int
color)作为what传入setSpan方法中,它表示要设置的Span效果是设置前景色。还有很多其他的,比如newBackgroundColorSpan(int
color),则对应背景色。

无论what使用哪种,一定要注意一个问题:每个CharacterStyle对象只能应用于一个Spanned,也就是说每个CharacterStyle对象只能使用一次。如果在给定的String中对多个字符应用,则只有最后一次应用会起作用。

要想多次使用,可以调用CharacterStyle类的静态方法wrap方法:

public static CharacterStyle wrap (CharacterStyle cs)

API是这样描述的:



意思总归一句话:使用wrap方法并传入一个CharacterStyle对象,跟直接new一个CharacterStyle对象然后传入setSpan方法中的效果是一样的。

下面给一个小小的例子来说明(这里代码很少,为了能看清每个变量的类型,我把所有变量的定义都写在了onCreate方法里面了):

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.textColorTest_tv);
String str = "你好,安卓-》Hello,Android!";
SpannableStringBuilder builder = new SpannableStringBuilder(str);
ForegroundColorSpan[] colorSpan = {new ForegroundColorSpan(Color.RED),
new ForegroundColorSpan(Color.GREEN), new ForegroundColorSpan(Color.BLUE),
new ForegroundColorSpan(Color.WHITE), new ForegroundColorSpan(Color.BLACK)};
int length = "你好,安卓-》Hello,World".length();
int rand;
for (int i = 1; i < length; i++) {
rand = (int) (Math.random() * 5);
while (rand == 5) {
rand = (int) (Math.random() * 5);
}
builder.setSpan(CharacterStyle.wrap(colorSpan[rand]), i - 1, i, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
//            builder.setSpan(colorSpan[rand], i - 1, i, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
tv.setText(builder);
}


代码中应用第18行的效果如图:



但是应用第19行,注释掉18行,效果是这样的:



两者的效果差异还是很明显的。第二个很明显前面很多字符都是黑的而除了黑色其他的颜色都只出现了一次,且位置比较靠后,已打印随机数查看log,并不是因为随机生成的是黑色的。

这个坑,大家注意!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息