OK,該解決方案是非常複雜的,但它的工作。我們需要一個自定義InputFilter
和一個SpanWatcher
。開始吧。
第一步很簡單。我們設置一個帶有圖像跨度的不可編輯前綴,並在該前綴後面設置光標。
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());
然後我們設置一個InputFilter
,以防止與編輯跨度的前綴。可以通過移動正在編輯的範圍,使其在前綴後面開始。
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;
}
}
}
});
然後我們創建一個SpanWatcher
,能夠檢測選擇的變化和移動選擇了前綴範圍。
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);
}
}
}
};
最後我們只是將SpanWatcher
添加到文本中。
edit.getText().setSpan(watcher, 0, 0, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
而就是這樣。因此,比較這種解決方案,只是增加一個TextWatcher
我寧願後一種方法。
有很多方法可以完成你想要的功能,比如設置一個自定義的'InputFilter'或者創建一個'TextView'的子類,並提供你自己的'InputConnection'實現,並覆蓋一些方法。但是使用'TextWatcher'是我知道的最簡單的解決方案。 – Michael
所以,你是說沒有Spannable屬性來設置處理這個? –
有一種方法我沒有提到。我會寫它作爲答案。 – Michael