android EditText – événement de frappe terminé

Je veux attraper un événement lorsque l’utilisateur a fini de modifier EditText.

Comment ceci peut être fait?

Lorsque l’utilisateur a terminé l’édition, il / elle va appuyer sur Done ou Enter

 ((EditText)findViewById(R.id.youredittext)).setOnEditorActionListener( new EditText.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE || event != null && event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { if (event == null || !event.isShiftPressed()) { // the user is done typing. return true; // consume. } } return false; // pass on to other listeners. } } ); 

De manière plus efficace, vous pouvez également utiliser EditText onFocusChange listener pour vérifier si l’utilisateur a effectué l’édition: (Il n’est pas nécessaire que l’ utilisateur appuie sur le bouton Terminé ou Entrée sur le clavier logiciel).

  ((EditText)findViewById(R.id.youredittext)).setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { /* When focus is lost check that the text field * has valid values. */ if (!hasFocus) { validateInput(v); } } }); 

Je préfère personnellement l’envoi automatique après la fin de la frappe. Voici comment détecter cet événement.

Déclarations et initialisation:

 private Timer timer = new Timer(); private final long DELAY = 1000; // in ms 

Listener in eg onCreate ()

 EditText editTextStop = (EditText) findViewById(R.id.editTextStopId); editTextStop.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(final CharSequence s, int start, int before, int count) { if(timer != null) timer.cancel(); } @Override public void afterTextChanged(final Editable s) { //avoid sortingggering event when text is too short if (s.length() >= 3) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // TODO: do what you need here (refresh list) // you will probably need to use // runOnUiThread(Runnable action) for some specific // actions serviceConnector.getStopPoints(s.toSsortingng()); } }, DELAY); } } }); 

Ainsi, lorsque le texte est modifié, le temporisateur commence à attendre les prochaines modifications. Quand ils se produisent, la timer est annulée puis recommencée.

Vous pouvez le faire en utilisant setOnKeyListener ou en utilisant un textWatcher comme:

Définir l’observateur de texte editText.addTextChangedListener(textWatcher);

puis appelle

 private TextWatcher textWatcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //after text changed } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }; 

@Reno et @Vinayak B répondent ensemble si vous souhaitez masquer le clavier après l’action

 textView.setOnEditorActionListener(new EditText.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(textView.getWindowToken(), 0); return true; } return false; } }); textView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { // your action here } } }); 

Bien que de nombreuses réponses soient dans la bonne direction, je pense qu’aucune d’entre elles ne répond à ce à quoi l’auteur de la question pensait. Ou du moins j’ai compris la question différemment parce que je cherchais une réponse à un problème similaire. Le problème est “Comment savoir quand l’utilisateur arrête de taper sans qu’il appuie sur un bouton” et déclenche une action (par exemple, une saisie automatique). Si vous voulez faire cela, démarrez le minuteur dans onTextChanged avec un délai que vous considéreriez comme arrêté par l’utilisateur (par exemple 500-700ms), pour chaque nouvelle lettre lorsque vous démarrez le minuteur, annulez la précédente (ou utilisez au moins une sorte de signaler que quand ils cochent ils ne font rien). Voici un code similaire à celui que j’ai utilisé:

 new Timer().schedule(new TimerTask() { @Override public void run() { if (!running) { new DoPost().execute(s.toSsortingng()); }); } }, 700); 

Notez que je modifie l’indicateur booléen en cours d’exécution dans ma tâche asynchrone (la tâche obtient le json du serveur pour l’auto-complétion).

Gardez également à l’esprit que cela crée de nombreuses tâches de timer (je pense qu’elles sont programmées sur le même thread mais vous devriez vérifier cela), donc il y a probablement beaucoup d’endroits à améliorer mais cette approche fonctionne également et l’essentiel est que vous devriez utiliser un minuteur, car il n’y a pas “L’utilisateur a cessé de taper un événement”

D’accord, cela fonctionnera à 100% à coup sûr.

Vous devez d’abord configurer l’auditeur si le clavier est affiché ou masqué. Si le clavier est affiché, l’utilisateur est probablement en train de taper, sinon vous devez taper.

 final View activityRootView = findViewById(android.R.id.content); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); //r will be populated with the coordinates of your view that area still visible. activityRootView.getWindowVisibleDisplayFrame(r); int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top); if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard... isTyping = true; } else { //to make sure this will call only once when keyboard is hide. if(isTyping){ isTyping = false; } } } }); 

Une approche différente … voici un exemple: si l’utilisateur a un délai de 600-1000 ms au moment de la frappe, vous pouvez considérer qu’il est arrêté.

  myEditText.addTextChangedListener(new TextWatcher() { private Ssortingng s; private long after; private Thread t; private Runnable runnable_EditTextWatcher = new Runnable() { @Override public void run() { while (true) { if ((System.currentTimeMillis() - after) > 600) { Log.d("Debug_EditTEXT_watcher", "(System.currentTimeMillis()-after)>600 -> " + (System.currentTimeMillis() - after) + " > " + s); // Do your stuff t = null; break; } } } }; @Override public void onTextChanged(CharSequence ss, int start, int before, int count) { s = ss.toSsortingng(); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable ss) { after = System.currentTimeMillis(); if (t == null) { t = new Thread(runnable_EditTextWatcher); t.start(); } } }); 

J’avais le même problème et je ne voulais pas que l’utilisateur appuie sur Done ou Enter.

Ma première tentative consistait à utiliser le programme d’écoute onFocusChange, mais il s’est avéré que mon EditText avait le focus par défaut. Lorsque l’utilisateur a appuyé sur une autre vue, le onFocusChange a été déclenché sans que l’utilisateur ne lui ait jamais atsortingbué le focus.

La solution suivante l’a fait pour moi, où onFocusChange est attaché si l’utilisateur a touché le texte EditText:

 final myEditText = new EditText(myContext); //make final to refer in onTouch myEditText.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { myEditText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if(!hasFocus){ // user is done editing } } } } } 

Dans mon cas, lorsque l’utilisateur a terminé la modification de l’écran, celui-ci a été renvoyé, renouvelant ainsi l’object myEditText. Si le même object est conservé, vous devez probablement supprimer le programme d’écoute onFocusChange dans onFocusChange pour empêcher le problème onFocusChange décrit au début de cette publication.

J’ai eu le même problème en essayant d’implémenter ‘maintenant la frappe’ sur l’application de chat. essayez d’étendre EditText comme suit:

 public class TypingEditText extends EditText implements TextWatcher { private static final int TypingInterval = 2000; public interface OnTypingChanged { public void onTyping(EditText view, boolean isTyping); } private OnTypingChanged t; private Handler handler; { handler = new Handler(); } public TypingEditText(Context context, AtsortingbuteSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.addTextChangedListener(this); } public TypingEditText(Context context, AtsortingbuteSet attrs) { super(context, attrs); this.addTextChangedListener(this); } public TypingEditText(Context context) { super(context); this.addTextChangedListener(this); } public void setOnTypingChanged(OnTypingChanged t) { this.t = t; } @Override public void afterTextChanged(Editable s) { if(t != null){ t.onTyping(this, true); handler.removeCallbacks(notifier); handler.postDelayed(notifier, TypingInterval); } } private Runnable notifier = new Runnable() { @Override public void run() { if(t != null) t.onTyping(TypingEditText.this, false); } }; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { } 

}

Je l’ai terminée avec le même problème et je ne pouvais pas utiliser la solution avec onEditorAction ou onFocusChange et je ne voulais pas essayer la timer. Une timer est trop dangereuse pour que vous puissiez goûter, à cause de tous les threads et trop imprévisible, car vous ne savez pas quand votre code est exécuté.

Le paramètre onEditorAction n’intercepte pas le départ de l’utilisateur sans bouton et si vous l’utilisez, notez que KeyEvent peut être nul. Le focus n’est pas fiable aux deux extrémités. L’utilisateur peut se concentrer et quitter sans saisir de texte ou sélectionner le champ et l’utilisateur n’a pas besoin de quitter le dernier champ EditText.

Ma solution utilise onFocusChange et un indicateur lorsque l’utilisateur commence à éditer du texte et une fonction pour obtenir le texte de la dernière vue focalisée, que j’appelle en cas de besoin.

Je viens de mettre l’accent sur tous mes champs de texte pour tracer le code d’affichage de texte de congé. Le code clearFocus n’est exécuté que si le champ a le focus. J’appelle la fonction dans onSaveInstanceState, je n’ai donc pas besoin d’enregistrer l’indicateur (mEditing) en tant qu’état de la vue EditText et lorsque des boutons importants sont cliqués et lorsque l’activité est fermée.

Soyez prudent avec TexWatcher car il est souvent appelé j’utilise la condition sur focus pour ne pas réagir lorsque le code onRestoreInstanceState entre du texte. je

 final EditText mEditTextView = (EditText) getView(); mEditTextView.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (!mEditing && mEditTextView.hasFocus()) { mEditing = true; } } }); mEditTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus && mEditing) { mEditing = false; ///Do the thing } } }); protected void saveLastOpenField(){ for (EditText view:getFields()){ view.clearFocus(); } } 

J’ai fait quelque chose comme cette classe abstraite qui peut être utilisée à la place du type TextView.OnEditorActionListener.

 abstract class OnTextEndEditingListener : TextView.OnEditorActionListener { override fun onEditorAction(textView: TextView?, actionId: Int, event: KeyEvent?): Boolean { if(actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT || event != null && event.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_ENTER) { if(event == null || !event.isShiftPressed) { // the user is done typing. return onTextEndEditing(textView, actionId, event) } } return false // pass on to other listeners } abstract fun onTextEndEditing(textView: TextView?, actionId: Int, event: KeyEvent?) : Boolean }