141 votes

Android EditText - événement de fin de frappe

Je veux attraper un événement lorsque l'utilisateur finit de modifier l'EditText.

Comment faire ?

1 votes

@PadmaKumar La façon la plus naturelle serait de perdre le focus sur l'EditText - alors l'utilisateur a définitivement terminé. Cependant, d'après mon expérience, il semble que tous les widgets Android ne récupèrent pas correctement le focus (j'ai eu ces problèmes avec les Spinners et les Buttons) - donc d'autres widgets pourraient ne pas perdre le focus...

3 votes

Pourquoi une si grande plateforme nous laisse-t-elle nous occuper de ce genre de fonctions simples ? google ne perdra rien à ajouter de telles fonctions principales à ses bibliothèques de support au moins.

0 votes

Si vous connaissez la longueur exacte de la chaîne que l'utilisateur va saisir, récupérez le texte dans afterTextChanged. Ex : override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }

199voto

Vinayak B Points 16555

Mieux encore, vous pouvez également utiliser l'écouteur EditText onFocusChange pour vérifier si l'utilisateur a terminé l'édition : (Il n'est pas nécessaire que l'utilisateur appuie sur la touche Done ou Enter du 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) { {
         // Validate youredittext
      }
    }
 });

Note : Pour plus d'un EditText, vous pouvez aussi laisser votre classe implémenter View.OnFocusChangeListener puis définissez les listeners pour chacun de vos EditText et validez-les comme ci-dessous

((EditText)findViewById(R.id.edittext1)).setOnFocusChangeListener(this);
((EditText)findViewById(R.id.edittext2)).setOnFocusChangeListener(this);

    @Override
    public void onFocusChange(View v, boolean hasFocus) {

      // When focus is lost check that the text field has valid values.

      if (!hasFocus) {
        switch (view.getId()) {
           case R.id.edittext1:
                 // Validate EditText1
                 break;
           case R.id.edittext2:
                 // Validate EditText2
                 break;
        }
      }
    }

67 votes

Cela ne fonctionne pas s'il n'y a qu'une seule cible. EditText . Il ne perdra jamais le fil.

0 votes

Quelle est la meilleure façon de procéder si nous n'avons qu'un seul EditText ? Dois-je utiliser onEditorAction ?

3 votes

S'il n'y a qu'un seul EditText vous validez sur ce que l'utilisateur fait pour quitter l'écran.

128voto

Reno Points 22138

Lorsque l'utilisateur a fini de modifier le texte, il appuie sur la touche Done o 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. 
        }
    }
);

55 votes

Pouvez-vous en être sûr ? J'ai l'habitude d'appuyer sur le champ éditable suivant - je n'appuie pratiquement jamais sur Enter/Done - et d'après ce que j'ai vu de nos clients, eux non plus... Je parle d'une liste d'Edittexts/Comboboxes etc. Si vous ne donnez à l'utilisateur qu'un seul champ de saisie et que vous l'obligez à appuyer sur un bouton avant de pouvoir passer aux autres champs, c'est évidemment une autre histoire...

6 votes

N'oubliez pas que vous devez également définir Android:singleLine="true" pour votre texte d'édition. Merci à stackoverflow.com/questions/15901863/

1 votes

Bonne solution mais peut se planter avec un pointeur nul... event' peut être nul sur l'action Done, donc event.isShiftPressed() se plante. Si vous utilisez cette solution, ajoutez des contrôles de pointeur nul.

24voto

ShineDown Points 678

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

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

puis appeler

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

        }
    };

31 votes

Je crains que ce ne soit pas la solution (complète) - le textWatcher se déclenche après chaque édition - si vous tapez hello, il va se déclencher pour h, e, l, l et o - il ne sait pas vraiment quand l'utilisateur a "fini". Ce serait génial si le TextWatcher pouvait savoir quand le widget perd le focus et que l'utilisateur passe à autre chose...

7voto

Tyler Davis Points 82

Les deux réponses @Reno et @Vinayak B ensemble si vous voulez cacher 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
        }
    }
});

5voto

PSIXO Points 583

Bien que de nombreuses réponses aillent 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 car 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éclencher une action (par exemple l'auto-complétion). Si vous voulez faire cela, démarrez le timer dans onTextChanged avec un délai que vous considérez que l'utilisateur a arrêté de taper (par exemple 500-700ms), pour chaque nouvelle lettre quand vous démarrez le timer, annulez le précédent (ou au moins utilisez une sorte de drapeau 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.toString());
  });
 }
}, 700);

Notez que je modifie le drapeau booléen en cours d'exécution dans ma tâche asynchrone (la tâche reçoit le json du serveur pour l'autocomplétion).

Gardez également à l'esprit que cela crée de nombreuses tâches de minuterie (je pense qu'elles sont programmées sur le même Thread thou mais il faudrait le vérifier), il y a donc probablement de nombreux endroits à améliorer mais cette approche fonctionne également et l'essentiel est que vous devriez utiliser une minuterie puisqu'il n'y a pas d'événement "User stopped typing".

0 votes

Pouvez-vous donner plus d'informations et un exemple de code à ce sujet ?

0 votes

L'essentiel du code est dans la réponse, pour un exemple plus détaillé, voir la réponse de ZimaXXX sur cette même page qui utilise la même approche. Je ne sais pas quelles autres informations je pourrais ajouter, si vous pouvez préciser ce qui n'est pas clair, j'essaierai d'ajouter des détails.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X