Android перехватывает вставку \ копирование \ вырезание при редактировании текста

Как я могу перехватить такого рода события?

Мне нужно добавить немного логики, когда пользователь пытается вставить текст в мой EditText я знаю, что могу использовать TextWatcher но эта точка входа не подходит для меня, потому что мне нужно только перехватить в случае вставки, а не каждый раз, когда пользователь нажимает мой EditText,

2 ответа

Решение

Похоже, что вы ничего не можете сделать с помощью API: событие android paste

Источник чтения на помощь!

Я копался в Android-источнике TextView (EditText это TextView с некоторой другой конфигурацией) и обнаружил, что меню, используемое, чтобы предложить опции вырезать / копировать / вставить, просто изменено ContextMenu ( источник).

Как и для обычного контекстного меню, представление должно создать меню ( источник), а затем обработать взаимодействие в методе обратного вызова ( источник).

Потому что метод обработки public мы можем просто подключиться к нему, расширяя EditText и переписать метод, чтобы реагировать на различные действия. Вот пример реализации:

import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.Toast;

/**
 * An EditText, which notifies when something was cut/copied/pasted inside it.
 * @author Lukas Knuth
 * @version 1.0
 */
public class MonitoringEditText extends EditText {

    private final Context context;

    /*
        Just the constructors to create a new EditText...
     */
    public MonitoringEditText(Context context) {
        super(context);
        this.context = context;
    }

    public MonitoringEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public MonitoringEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    /**
     * <p>This is where the "magic" happens.</p>
     * <p>The menu used to cut/copy/paste is a normal ContextMenu, which allows us to
     *  overwrite the consuming method and react on the different events.</p>
     * @see <a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3_r1/android/widget/TextView.java#TextView.onTextContextMenuItem%28int%29">Original Implementation</a>
     */
    @Override
    public boolean onTextContextMenuItem(int id) {
        // Do your thing:
        boolean consumed = super.onTextContextMenuItem(id);
        // React:
        switch (id){
            case android.R.id.cut:
                onTextCut();
                break;
            case android.R.id.paste:
                onTextPaste();
                break;
            case android.R.id.copy:
                onTextCopy();
        }
        return consumed;
    }

    /**
     * Text was cut from this EditText.
     */
    public void onTextCut(){
        Toast.makeText(context, "Cut!", Toast.LENGTH_SHORT).show();
    }

    /**
     * Text was copied from this EditText.
     */
    public void onTextCopy(){
        Toast.makeText(context, "Copy!", Toast.LENGTH_SHORT).show();
    }

    /**
     * Text was pasted into the EditText.
     */
    public void onTextPaste(){
        Toast.makeText(context, "Paste!", Toast.LENGTH_SHORT).show();
    }
}

Теперь, когда пользователь использует вырезать / копировать / вставить, Toast отображается (конечно, вы могли бы делать и другие вещи).

Важно то, что это работает вплоть до Android 1.5, и вам не нужно заново создавать контекстное меню (как предложено в приведенном выше связанном вопросе), которое будет поддерживать постоянный вид платформы (например, с HTC Sense).).

Существует гораздо более простой способ, хотя и не на 100% надежный.

Добавьте TextChangedListener к вашему окну редактирования:

EditText et = (EditText) mView.findViewById(R.id.yourEditText);
et.addTextChangedListener(new TextWatcher() {

  @Override
  public void onTextChanged(CharSequence s, int start, int before, int count) {
     if (count > 2) toast("text was pasted");
  }

  @Override
  public void beforeTextChanged(CharSequence s, int start, int count, int after) {

  }

  public void afterTextChanged(Editable s) {

  }
});

Если текст изменяется более чем на 2 символа, можно предположить, что он был вставлен (некоторые смайлики занимают два символа).

Конечно, он не будет обнаруживать вставку, когда пользователь вставляет 1 или два символа, и будет ложно сообщать о вставке, если изменение в тексте было вызвано чем-то другим.

Но для большинства целей он выполняет свою работу.

Другие вопросы по тегам