摘要: SpannableStringBuilder 错误地使用 InputFilter::filter(...) 的 'end' 参数来放置 'source' 的长度
背景
InputFilter 有以下方法:
abstract CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
根据官方文档:
当缓冲区要将范围 dstart ... dend of dest 替换为范围 start ... end of source 的新文本时,将调用此方法。
我们感兴趣的参数是end
支持证据:
1) robolectric 单元测试(在实际的 android 设备上测试结果相同):
@RunWith(RobolectricTestRunner.class)
public class playground
{
static int mTestNumber; //so know which testcase is being run in filter();
@Test
public void test_SpannableStringBuilder()
{
SpannableStringBuilder ssb;
InputFilter inputFilter;
inputFilter = new InputFilter()
{
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
{
int[] expected,
results;
results= new int[] {start, end, dstart, dend};
switch (mTestNumber)
{
case 0: //"0123" appended to default initialization (empty string?)
expected= new int[] {0, 3, 0, 0};
Assert.assertArrayEquals(expected, results); // fails since end=4.
break;
}
return null;
}
};
mTestNumber= 0;
ssb= new SpannableStringBuilder(""); //internally stored as 2 chars" "0\0"
ssb.setFilters((new InputFilter[] {inputFilter}));
ssb.append("0123");
return;
}
} ///END CLASS///
(开始,结束)应该是(0,3)
但是当测试运行时:
(开始,结束)=(0,4)
看来end正在返回长度
进一步挖掘:
查看 SpannableStringBuilder 我们有:
SpannableStringBuilder append(CharSequence text)
替换方便(length(), length(), text, 0, text.length())
接着
SpannableStringBuilder replace(int start, int end, CharSequence tb, int tbstart, int tbend)
将此 Editable 中指定的文本范围 (st...en) 替换为来自源的切片 start...end 的副本。
注意:
1) append() 将 text.length() 放入 tbend (我相信这是错误的来源)
2) replace() 文档有错误的参数名称
想法
这看起来是一个非常明显的错误,尤其是因为它基本上使 InputFilter 无法与 EditText 一起使用,除了最简单的情况。我一直无法找到有关此错误的任何信息。我很难相信它以前没有出现过。我在这里错过了什么吗?