OK, ist die Lösung ziemlich kompliziert, aber es funktioniert. Wir benötigen eine benutzerdefinierte InputFilter
und eine SpanWatcher
. Lasst uns beginnen.
Der erste Schritt ist ziemlich einfach. Wir setzen ein nicht editierbares Präfix mit einer Bildspanne und setzen einen Cursor nach diesem Präfix.
final String prefix = "?";
final ImageSpan image = new ImageSpan(this, R.drawable.image);
edit.setText(prefix);
edit.getText().setSpan(image, 0, prefix.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
edit.setSelection(prefix.length());
Dann setzten wir ein InputFilter
, die das Präfix mit der Spanne von der Bearbeitung verhindern. Sie können einen Bereich bearbeiten, der bearbeitet wird, sodass er nach dem Präfix beginnt.
edit.setFilters(new InputFilter[] {
new InputFilter() {
@Override
public CharSequence filter(final CharSequence source, final int start,
final int end, final Spanned dest, final int dstart, final int dend) {
final int newStart = Math.max(prefix.length(), dstart);
final int newEnd = Math.max(prefix.length(), dend);
if (newStart != dstart || newEnd != dend) {
final SpannableStringBuilder builder = new SpannableStringBuilder(dest);
builder.replace(newStart, newEnd, source);
if (source instanceof Spanned) {
TextUtils.copySpansFrom(
(Spanned) source, 0, source.length(), null, builder, newStart);
}
Selection.setSelection(builder, newStart + source.length());
return builder;
} else {
return null;
}
}
}
});
Dann erstellen wir eine SpanWatcher
die Auswahl ändert und bewegen Sie die Auswahl aus dem Präfix Bereich erkennt.
final SpanWatcher watcher = new SpanWatcher() {
@Override
public void onSpanAdded(final Spannable text, final Object what,
final int start, final int end) {
// Nothing here.
}
@Override
public void onSpanRemoved(final Spannable text, final Object what,
final int start, final int end) {
// Nothing here.
}
@Override
public void onSpanChanged(final Spannable text, final Object what,
final int ostart, final int oend, final int nstart, final int nend) {
if (what == Selection.SELECTION_START) {
if (nstart < prefix.length()) {
final int end = Math.max(prefix.length(), Selection.getSelectionEnd(text));
Selection.setSelection(text, prefix.length(), end);
}
} else if (what == Selection.SELECTION_END) {
final int start = Math.max(prefix.length(), Selection.getSelectionEnd(text));
final int end = Math.max(start, nstart);
if (end != nstart) {
Selection.setSelection(text, start, end);
}
}
}
};
Und schließlich fügen wir nur die SpanWatcher
auf den Text.
edit.getText().setSpan(watcher, 0, 0, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
Und das ist alles. Bei einem Vergleich dieser Lösung mit einer TextWatcher
würde ich den letzteren Ansatz bevorzugen.
Es gibt mehrere Möglichkeiten, wie Sie einen benutzerdefinierten 'InputFilter' oder eine'TextView'unterklassifizieren und eine eigene Implementierung von' InputConnection' mit einigen überschriebenen Methoden bereitstellen können. Aber die Verwendung eines 'TextWatcher' ist die einfachste Lösung, die mir bekannt ist. – Michael
Also, sagen Sie, es gibt keine spannbaren Eigenschaften, um dies zu handhaben? –
Es gibt eine Methode, die ich nicht erwähnt habe. Ich werde es als Antwort schreiben. – Michael