2

摘要: 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 一起使用,除了最简单的情况。我一直无法找到有关此错误的任何信息。我很难相信它以前没有出现过。我在这里错过了什么吗?

4

0 回答 0