public void setSpan(Object what, int start,int end,int flags)
参数1 what: 各种Span 比如字体大小、字体颜色等
参数2 start : 所要修改字符下标开始位置,修改会包含start这个位置
参数2 end : 所要修改字符下标结束位置,不包含该位置字符
参数2 flags: 一般有四个常用模式,下面会提,这个flag和前两个参数start和end没有任何关系,就是它
不是用来控制前两个参数的
下面就说几个经常搞不清的情况
1 start 和 end 问题
当你操作TextView的时候,无论你把flags参数设置为哪种模式,都不会影响 start 和 end,字符改变的位置包含start位置不包含end位置
如图: start:1 ; end:6 . 图中字符下标 [1]-[5]的字符字体变大 ,无论flags是什么都不会影响变大字体的位置
图中字符串长度为10 下标对应 [0]-[9]
如图 start:1 ; end:10 图中字符下标 [1]-[9]的字符字体变大
但是如果你end 输入11,程序就会崩溃,直接出现异常。10也超出这个字符的下标了为啥10就不会出错呢?
看源码:
/* package */ void setSpan(Object what, int start, int end, int flags) {
int nstart = start;
int nend = end;
checkRange("setSpan", start, end);//①:检查 start和end是否符合要求
if ((flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPH) {
if (start != 0 && start != length()) {
char c = charAt(start - 1);
if (c != '\n')
throw new RuntimeException(
"PARAGRAPH span must start at paragraph boundary" +
" (" + start + " follows " + c + ")");
}
if (end != 0 && end != length()) {
char c = charAt(end - 1);//②:看到这个就明白为啥不包含end了
if (c != '\n')
throw new RuntimeException(
"PARAGRAPH span must end at paragraph boundary" +
" (" + end + " follows " + c + ")");
}
}
checkRange(.....) 方法是什么样的?
private void checkRange(final String operation, int start, int end) {
if (end < start) {
throw new IndexOutOfBoundsException(operation + " " +
region(start, end) +
" has end before start");
}
int len = length();//这个length就是所要操作的字符串长度,就不贴源码了
//通过比较end是否已超过字符串长度,若超过则抛出异常。
// 因为上方② 处会charAt(end - 1)
if (start > len || end > len) {
throw new IndexOutOfBoundsException(operation + " " +
region(start, end) +
" ends beyond length " + len);
}
if (start < 0 || end < 0) {
throw new IndexOutOfBoundsException(operation + " " +
region(start, end) +
" starts before 0");
}
}
2 flags到底是干什么用的,什么时候会起作用呢?
当你不是操作TextView而是EditText这种可以输入的文本的时候,flags就起作用了。
你已经将某段字符做出改变,而你在所改变内容前后输入新的内容时,就会根据flags有所变化。
直接放图 看了就更容易明白:
1 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 前后都不包含
图中字母a是改变字体大小后输入的,SPAN_EXCLUSIVE_EXCLUSIVE模式,大小不会发生改变。
2 Spanned.SPAN_EXCLUSIVE_INCLUSIVE 不包含前面 包含后面
如图 在改变字体大小后输入A, 前面A没有变大,后面的变大
3 Spanned.SPAN_INCLUSIVE_EXCLUSIVE 包含前面,不包含后面
4 Spanned.SPAN_INCLUSIVE_INCLUSIVE 前后都包含
总结一下,flags是对可以输入新文本的控件才会起作用,如果你是对TextView操作,flags用哪个都一样的。