7

我一直在尝试解决零长度格式 Spans 的 android 问题。我想,好吧,我将删除长度为零的 Span。在环顾四周后,我认为 SpanWatcher 将是一个很好的方法。然而,似乎缺乏关于如何实现或添加 SpanWatchers 的示例。

我在 MonoDroid 中试过这个:

public class PreventZeroLenSpan : Java.Lang.Object, ISpanWatcher
{
    void ISpanWatcher.OnSpanAdded (ISpannable text, Java.Lang.Object what, int start, int end)
    {
        if (what==this) return;
        var CS = what as Android.Text.Style.CharacterStyle;
        if (CS==null) return;
        if (start==end) text.RemoveSpan(CS);
    }

    void ISpanWatcher.OnSpanChanged (ISpannable text, Java.Lang.Object what, int ostart, int oend, int nstart, int nend)
    {
        if (what==this) return;
        var CS = what as Android.Text.Style.CharacterStyle;
        if (CS==null) return;
        if (nstart==nend) text.RemoveSpan(CS);
    }

    void ISpanWatcher.OnSpanRemoved (ISpannable text, Java.Lang.Object what, int start, int end)
    {
        // nothing
    }
}

如果我先将其直接添加到 SpannableStringBuilder 或 SpannableString,则会调用这些事件,但是在它进入 EditText 控件之后它不再响应。

        var Str = new SpannableStringBuilder("Test IT");
        var Sty = new ForegroundColorSpan(Android.Graphics.Color.Blue);
        Str.SetSpan(SpanWatch,0,Str.Length(), SpanTypes.InclusiveInclusive);
        Str.SetSpan(Sty,5,7, SpanTypes.InclusiveInclusive);
        txEdit.SetText(Str, TextView.BufferType.Editable);

SpanWatcher 实现了 NoCopySpan,因此它不会被复制到 EditText 中。我找不到任何将 SpanWatcher 直接添加到 EditText 的方法(有一种方法可以添加 TextWatcher)。

我想如果我无法弄清楚 SpanWatcher,我可以在每次文本更改时扫描整个内容的零长度跨度。只是看起来效率低下。(稍后我可能需要为我的图形换行指示器删除事件。)

任何想法都值得赞赏,欢迎使用 Java 或 MonoDroid 中的示例。

编辑

我仍然有兴趣知道如何使用 SpanWatcher 执行此操作(似乎更有效),但对于其他在零长度 Span 移除方面苦苦挣扎的人,您可以使用以下 TextWatcher 执行 EditText.AddTextChangedListener():

public class PreventZeroLenSpanWatcher : Java.Lang.Object, ITextWatcher
{
    void ITextWatcher.AfterTextChanged (IEditable s)
    {
        var Objs = s.GetSpans(0,s.Length(), Java.Lang.Class.FromType(typeof(Android.Text.Style.CharacterStyle)));
        foreach (Android.Text.Style.CharacterStyle CS in Objs)
        {
            int Start = s.GetSpanStart(CS);
            int End = s.GetSpanEnd(CS);
            if (Start == End) s.RemoveSpan(CS);
        }
    }

    void ITextWatcher.BeforeTextChanged (Java.Lang.ICharSequence s, int start, int count, int after)
    {
        // nothing
    }

    void ITextWatcher.OnTextChanged (Java.Lang.ICharSequence s, int start, int before, int count)
    {
        // nothing
    }
}

编辑2

如果你这样做,你至少可以让 SpanWatcher 进入 EditText,但是一旦用户编辑文本,你似乎又失去了它。控件内部必须进行一些复制,并且 SpanWatcher 不可复制。

        IEditable txEditFormatted = ((IEditable)txEdit.TextFormatted);
        txEditFormatted.SetSpan(SpanWatch,0,txEditFormatted.Length(), SpanTypes.InclusiveInclusive);

我还尝试使用 TextWatcher 重新添加 SpanWatcher,但到那时跨度已经改变。

4

0 回答 0