長さゼロのフォーマット Spans を使用した Android の問題の回避策を見つけようとしています。長さがゼロになるスパンを削除するだけです。少し調べた後、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 でこれを行う方法を知りたいと思っています (より効率的です) が、長さゼロのスパンの削除に苦労している他の人のために、次の 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
}
}
EDIT2
これを行うと、少なくとも SpanWatcher を EditText に入れることができますが、ユーザーがテキストを編集すると、再び失われたように見えます。コントロールによって内部的に行われる何らかのコピーが必要であり、SpanWatcher はコピーできません。
IEditable txEditFormatted = ((IEditable)txEdit.TextFormatted);
txEditFormatted.SetSpan(SpanWatch,0,txEditFormatted.Length(), SpanTypes.InclusiveInclusive);
また、TextWatcher を使用して SpanWatcher を再追加しようとしましたが、その時までにスパンは既に変更されていました。