Je veux attraper un événement lorsque l'utilisateur a fini de modifier EditText.
Comment ceci peut être fait?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Je veux attraper un événement lorsque l'utilisateur a fini de modifier EditText.
Comment ceci peut être fait?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Réponses:
Lorsque l'utilisateur a terminé l'édition, il / elle appuiera sur Done
ouEnter
((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.
}
}
);
Mieux, vous pouvez également utiliser l'écouteur EditText onFocusChange pour vérifier si l'utilisateur a terminé la modification: (Ne comptez pas sur l'utilisateur appuyant sur le bouton Terminé ou Entrée 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
}
}
});
Remarque: pour plus d'un EditText, vous pouvez également laisser votre classe implémenter View.OnFocusChangeListener
puis définir les écouteurs sur chacun de vous EditText et les valider 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;
}
}
}
EditText
. Il ne perdra jamais sa concentration.
EditText
? Dois-je utiliser onEditorAction
?
EditText
, vous validez ce que fait l'utilisateur pour quitter l'écran.
W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=605.52246, y[0]=969.4336, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=238238, downTime=235422, deviceId=0, source=0x1002 }
même si j'ai tapé quelque chose. C'est un edittext qui n'accepte que les nombres.
Personnellement, je préfère la soumission automatique après la fin de la saisie. Voici comment vous pouvez détecter cet événement.
Déclarations et initialisation:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Écouteur dans par exemple 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 triggering 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.toString());
}
}, DELAY);
}
}
});
Ainsi, lorsque le texte est modifié, le minuteur commence à attendre les prochains changements. Quand ils se produisent, la minuterie est annulée puis redémarrée.
Handler
place
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) {
}
};
Bien que de nombreuses réponses pointent dans la bonne direction, je pense qu'aucune d'elles ne répond à ce à quoi pensait l'auteur de la question. 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éclencher une action (par exemple l'auto-complétion). Si vous voulez faire cela, démarrez le minuteur 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 lorsque vous démarrez le minuteur, annulez la précédente (ou au moins utilisez une sorte de signalent que lorsqu'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 obtient le json du serveur pour l'auto-complétion).
Gardez également à l'esprit que cela crée de nombreuses tâches de minuterie (je pense qu'elles sont planifiées sur le même fil de discussion que vous, mais vous devriez vérifier cela), il y a donc probablement de nombreux endroits à améliorer, mais cette approche fonctionne également et l'essentiel est que vous devriez utiliser un minuteur car il n'y a pas d'événement "L'utilisateur a arrêté de taper"
@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
}
}
});
Une approche différente ... voici un exemple: si l'utilisateur a un délai de 600 à 1000 ms lors de la frappe, vous pouvez considérer qu'il est arrêté.
myEditText.addTextChangedListener(new TextWatcher() {
private String 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.toString();
}
@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();
}
}
});
D'accord, cela fonctionnera à 100% à coup sûr.
Vous devrez d'abord configurer l'écouteur si le clavier est affiché ou masqué. Si le clavier est affiché, l'utilisateur est probablement en train de taper, sinon il est terminé.
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;
}
}
}
});
heightDiff > 100
truc est effrayant à mon humble avis.
J'ai résolu ce problème de cette façon. J'ai utilisé du kotlin.
var timer = Timer()
var DELAY:Long = 2000
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
Log.e("TAG","timer start")
timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
//do something
}
}, DELAY)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
Log.e("TAG","timer cancel ")
timer.cancel() //Terminates this timer,discarding any currently scheduled tasks.
timer.purge() //Removes all cancelled tasks from this timer's task queue.
}
})
J'ai eu le même problème et je ne voulais pas compter sur l'utilisateur appuyant sur Terminé ou Entrée.
Ma première tentative a été d'utiliser l'écouteur onFocusChange, mais il est arrivé que mon EditText ait le focus par défaut. Lorsque l'utilisateur appuyait sur une autre vue, onFocusChange était déclenché sans que l'utilisateur lui ait jamais attribué le focus.
La solution suivante l'a fait pour moi, où le onFocusChange est attaché si l'utilisateur a touché le 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é de modifier l'écran a été rendu à nouveau, renouvelant ainsi l'objet myEditText. Si le même objet est conservé, vous devez probablement supprimer l'écouteur onFocusChange dans onFocusChange pour éviter le problème onFocusChange décrit au début de cet article.
J'ai eu le même problème en essayant d'implémenter la saisie instantanée 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, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.addTextChangedListener(this);
}
public TypingEditText(Context context, AttributeSet 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 minuterie. Une minuterie est trop dangereuse pour peut goûter, à cause de tous les threads et trop imprévisible, car vous ne savez pas quand votre code est exécuté.
OnEditorAction n'attrape pas lorsque l'utilisateur quitte sans utiliser de 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 obtenir le focus et quitter sans entrer 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 défini 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 d'effacer le focus sur tous mes champs de texte pour tromper le code de vue de texte de congé, le code clearFocus n'est exécuté que si le champ a le focus. J'appelle la fonction dans onSaveInstanceState afin de ne pas avoir à enregistrer l'indicateur (mEditing) comme é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 le 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
}
Simple à déclencher, terminer la saisie dans EditText
a fonctionné pour moi, si vous utilisez java, convertissez-le
À Kotlin
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}