2013-02-20 19 views
27

Jak mogę przechwycić tego rodzaju zdarzenia?Wklej do przechwytywania systemu Android copy cut on editText

Potrzebuję dodać trochę logiki, gdy użytkownik próbuje wkleić tekst do mojego EditText wiem, że mogę używać TextWatcher, ale ten punkt początkowy nie jest dla mnie dobry, ponieważ muszę przechwytywać tylko w przypadku wklejania, a nie za każdym razem, gdy użytkownik przyciskam EditText,

+0

Dobre wyzwanie. Spójrz na moją odpowiedź. –

Odpowiedz

62

Wydaje się, że nie ma wiele można zrobić za pomocą API: android paste event

Source reading to the rescue!

I wbił Źródło Android w TextView (EditText jest TextView z inną konfiguracją) i okazało się, że menu używane do oferowania opcji wycinania/kopiowania/wklejania jest po prostu zmodyfikowane ContextMenu().

W przypadku normalnego menu kontekstowego widok musi utworzyć menu (source), a następnie obsłużyć interakcję w metodzie wywołania zwrotnego (source).

Ponieważ sposób obsługi to public, możemy po prostu podłączyć się do niego poprzez rozszerzenie EditText i nadpisanie metody, aby zareagować na różne akcje. Oto przykład, realizacja:

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(); 
    } 
} 

Teraz, gdy użytkownik korzysta wytnij/kopiuj/wklej, o Toast jest pokazane (oczywiście można robić inne rzeczy też).

Schludny rzeczą jest to, że to działa aż do Android 1.5 i nie trzeba ponownie utworzyć kontekst-menu (jak sugeruje się w powyższej kwestii związanej), który będzie utrzymać stałą wygląd platforma (na przykład z HTC Sense).

+0

mam ** nie można utworzyć wystąpienia klasy brak pustego konstruktora ** błąd jakiego rozwiązania to ??? –

+0

cóż, klasa nie ma pustego konstruktora. musisz przekazać mu instancję 'Context' (jeśli twój kod znajduje się w działaniu, możesz przekazać go' this'). –

+0

Rozszerzyłeś swoje rozwiązanie za pomocą detektora, dzięki czemu można go używać jako komponentu plug & play. Istota https://gist.github.com/guillermomuntaner/82491cbf0c88dec560a5 – GuillermoMP

0

Istnieje o wiele prostszy sposób, chociaż nie jest w 100% niezawodny.

dodawania TextChangedListener do okna edycji:

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) { 

    } 
}); 

Jeśli zmiany tekstowe więcej niż 2 znaki, można założyć, że został wklejony (niektóre emotikony potrwać dwa znaki).

Oczywiście nie wykryje wklejenia, gdy użytkownik wklei 1 lub 2 znaki, i będzie fałszywie zgłaszał wklejanie, jeśli zmiana w tekście została wywołana przez coś innego.

Ale dla większości celów robi to zadanie.