Tamam, çözüm oldukça karmaşıktır ama işe yarıyor. Özel bir InputFilter
ve SpanWatcher
'a ihtiyacımız var. Hadi başlayalım.
İlk adım oldukça basit. Bir resim açıklığı ile düzenlenebilir olmayan bir ön ek ayarladık ve bu önekin ardından bir imleç ayarladık.
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());
Sonra düzenleme açıklıklı önek önleyecek bir
InputFilter
ayarlayın. Önceden sonra başlaması için düzenlenmekte olan bir menzili hareket ettirerek yapılabilir.
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;
}
}
}
});
Sonra seçim değişiklikleri saptamak ve önek aralığın dışında seçimini hareket edecek bir
SpanWatcher
oluşturun.
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);
}
}
}
};
Ve nihayet biz sadece metne SpanWatcher
ekleyin.
Ve hepsi bu. Yani bu çözümü sadece bir TextWatcher
ekleyerek karşılaştırmak, ikinci yaklaşımı tercih ederim.
Özel bir 'InputFilter' ayarlamak veya 'TextView' alt sınıfını oluşturmak ve 'InputConnection' kendi uygulamanızı geçersiz kılmanın bazı yöntemlerini sağlamak gibi istediğinizi yapmak için birden çok yol vardır. Ama 'TextWatcher' kullanmak benim bildiğim en basit çözümdür. – Michael
Yani, bunun üstesinden gelmek için kullanılacak bir Spannable özelliği yok mu? –
Bahsetmediğim bir yöntem var. Bir cevap olarak yazacağım. – Michael