EditText с SpannableStringBuilder и ImageSpan не работает нормально
Я пытаюсь поместить смайлики в EditText. Мне удалось сделать это, и он работает нормально, но у меня есть проблема, когда я пытаюсь удалить эти смайлики из EditText с помощью программной клавиатуры. Я не могу сделать это действие одним нажатием кнопки удаления. Когда я вставляю новый ImageSpan, я заменяю для него imageId, но когда я пытаюсь удалить значок de, мне нужно удалить все символы imageId перед удалением изображения.
String fileName = "emoticon1.png";
Drawable d = new BitmapDrawable(getResources(), fileName);
String imageId = "[" + fileName + "]";
int cursorPosition = content.getSelectionStart();
int end = cursorPosition + imageId.length();
content.getText().insert(cursorPosition, imageId);
SpannableStringBuilder ss = new SpannableStringBuilder(content.getText());
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
ss.setSpan(span, cursorPosition, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
content.setText(ss, TextView.BufferType.SPANNABLE);
content.setSelection(end);
Мне нужно удалить смайлики одним нажатием кнопки удаления. Не могли бы вы мне помочь, пожалуйста?
Спасибо!
1 ответ
Это реализация для обработки смайликов внутри EditText
, Эта реализация использует TextWatcher
контролировать EditText
изменяет и определяет, был ли удален какой-либо смайлик при удалении некоторого текста.
Обратите внимание, что эта реализация также проверяет, был ли удален выделенный текст (не только ключ удаления).
Чтобы избежать проблем с предсказанием текста при наборе текста, рекомендуется окружать текст смайлика пробелами (предсказание текста может объединять текст смайлика со смежным текстом).
package com.takamori.testapp;
import java.util.ArrayList;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.style.ImageSpan;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
public class MainActivity extends Activity {
private EmoticonHandler mEmoticonHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editor = (EditText) findViewById(R.id.messageEditor);
// Create the emoticon handler.
mEmoticonHandler = new EmoticonHandler(editor);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_insert_emoticon:
// WARNING: The emoticon text shall be surrounded by spaces
// to avoid issues with text prediction.
mEmoticonHandler.insert(" :-) ", R.drawable.smile);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private static class EmoticonHandler implements TextWatcher {
private final EditText mEditor;
private final ArrayList<ImageSpan> mEmoticonsToRemove = new ArrayList<ImageSpan>();
public EmoticonHandler(EditText editor) {
// Attach the handler to listen for text changes.
mEditor = editor;
mEditor.addTextChangedListener(this);
}
public void insert(String emoticon, int resource) {
// Create the ImageSpan
Drawable drawable = mEditor.getResources().getDrawable(resource);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
// Get the selected text.
int start = mEditor.getSelectionStart();
int end = mEditor.getSelectionEnd();
Editable message = mEditor.getEditableText();
// Insert the emoticon.
message.replace(start, end, emoticon);
message.setSpan(span, start, start + emoticon.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@Override
public void beforeTextChanged(CharSequence text, int start, int count, int after) {
// Check if some text will be removed.
if (count > 0) {
int end = start + count;
Editable message = mEditor.getEditableText();
ImageSpan[] list = message.getSpans(start, end, ImageSpan.class);
for (ImageSpan span : list) {
// Get only the emoticons that are inside of the changed
// region.
int spanStart = message.getSpanStart(span);
int spanEnd = message.getSpanEnd(span);
if ((spanStart < end) && (spanEnd > start)) {
// Add to remove list
mEmoticonsToRemove.add(span);
}
}
}
}
@Override
public void afterTextChanged(Editable text) {
Editable message = mEditor.getEditableText();
// Commit the emoticons to be removed.
for (ImageSpan span : mEmoticonsToRemove) {
int start = message.getSpanStart(span);
int end = message.getSpanEnd(span);
// Remove the span
message.removeSpan(span);
// Remove the remaining emoticon text.
if (start != end) {
message.delete(start, end);
}
}
mEmoticonsToRemove.clear();
}
@Override
public void onTextChanged(CharSequence text, int start, int before, int count) {
}
}
}