我一直在尝试解决零长度格式 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,但到那时跨度已经改变。