如何在不重新读取整个字符串的情况下通知已跨更改的EditText

时间:2017-06-19 23:36:37

标签: java android android-edittext

我正在编写一个语法高亮显示代码的Android应用。目前,该应用程序通过获取字符串,将其转换为new SpannableStringBuilder,然后根据文件扩展名通过setSpan(new ForegroundColorSpan(...))对其进行着色。完成所有操作后,将使用构建器调用EditText.setText。这种方法的问题在于大文件,所有setSpan调用都需要很长时间,并且在调用setText()并显示文本之前,UI会冻结10秒钟。

我想在这里彻底改变方法。我想首先在整个字符串上调用setText(),因此文本会立即显示(但是不显示)。然后我想分批为500行文本着色,每批后冲到显示器。用户可能不会注意到任何差异(除了perf)因为我可以处理+冲洗500行比用户可以向下滚动500行快得多。

但是,我不确定如何有效地实现我的想法。通过更新显示来“刷新”更改的唯一方法是在向其添加更多跨度后再次调用setText()上的SpannableStringBuilder。反过来,setText()重新读取整个字符串及其所有跨度,只需要查看新的跨度。是否可以告诉EditText只重绘新的跨度?感谢。

1 个答案:

答案 0 :(得分:0)

我是愚蠢的。在提出这个问题之前,我做了这个测试应用程序(使用Xamarin / C#):

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    SetContentView(Resource.Layout.Main);

    var editText = FindViewById<EditText>(Resource.Id.EditText);
    var ssb = new SpannableStringBuilder(new string('E', 250));
    editText.SetText(ssb, TextView.BufferType.Editable);
    ssb.SetSpan(new ForegroundColorSpan(Color.Blue), 0, ssb.Length(), SpanTypes.InclusiveExclusive);
}

当您运行该应用程序时,所有文本都是白色的。我认为这是因为EditText忽略了您在SetText之后所做的任何更改,并且您需要再次调用SetText才能使更改生效。但是,我记得EditText默认情况下会在您致电Editable时复制SetText,因此您必须事先添加此内容:

editText.SetEditableFactory(new NoCopyEditableFactory());

private class NoCopyEditableFactory : EditableFactory // Editable.Factory in Java
{
    public override IEditable NewEditable(ICharSequence source) => (IEditable)source;
}

现在所有文字都是蓝色的,即使我在SetSpan之后拨打SetText