Voglio catturare un evento quando l'utente finisce di modificare EditText.
Come si può fare?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Voglio catturare un evento quando l'utente finisce di modificare EditText.
Come si può fare?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Risposte:
Quando l'utente ha terminato la modifica, premerà Done
oEnter
((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.
}
}
);
In modo migliore, puoi anche utilizzare EditText onFocusChange listener per verificare se l'utente ha effettuato la modifica: (non è necessario fare affidamento sull'utente che preme il pulsante Fine o Invio sulla tastiera morbida)
((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
}
}
});
Nota: per più di un EditText, puoi anche lasciare che la tua classe implementi View.OnFocusChangeListener
quindi impostare gli ascoltatori su ciascuno di voi EditText e convalidarli come di seguito
((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
. Non perderà mai la concentrazione.
EditText
? Devo usare onEditorAction
?
EditText
, convalidi ciò che l'utente fa per lasciare lo schermo.
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 }
Anche se ho digitato qualcosa. Questo è un testo di modifica che accetta solo numeri.
Personalmente preferisco l'invio automatico dopo la fine della digitazione. Ecco come puoi rilevare questo evento.
Dichiarazioni e inizializzazione:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Listener in es. 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);
}
}
});
Quindi, quando il testo viene modificato, il timer inizia ad attendere che avvengano eventuali modifiche successive. Quando si verificano, il timer viene annullato e quindi riavviato.
Handler
invece
Puoi farlo usando setOnKeyListener o usando un textWatcher come:
Imposta l'osservatore di testo editText.addTextChangedListener(textWatcher);
quindi chiama
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) {
}
};
Sebbene molte risposte puntino nella giusta direzione, penso che nessuna di esse risponda a ciò a cui stava pensando l'autore della domanda. O almeno ho capito la domanda in modo diverso perché cercavo una risposta a un problema simile. Il problema è "Come sapere quando l'utente smette di digitare senza che lui prema un pulsante" e attiva un'azione (ad esempio il completamento automatico). Se vuoi farlo, avvia il Timer in onTextChanged con un ritardo che considereresti che l'utente abbia smesso di digitare (ad esempio 500-700ms), per ogni nuova lettera quando avvii il timer annulla quella precedente (o almeno usa una sorta di segnala che quando spuntano non fanno nulla). Ecco un codice simile a quello che ho usato:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
Si noti che modifico l'esecuzione del flag booleano all'interno della mia attività asincrona (l'attività ottiene il json dal server per il completamento automatico).
Tieni anche presente che questo crea molte attività del timer (penso che siano programmate sullo stesso thread tu ma dovresti controllarlo), quindi probabilmente ci sono molti posti per migliorare ma anche questo approccio funziona e la linea di fondo è che dovresti utilizza un timer poiché non è presente alcun "evento di digitazione interrotto dall'utente"
sia @Reno che @Vinayak B rispondono insieme se vuoi nascondere la tastiera dopo l'azione
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
}
}
});
Un approccio diverso ... ecco un esempio: se l'utente ha un ritardo di 600-1000 ms durante la digitazione, potresti considerare che è fermo.
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();
}
}
});
Va bene, funzionerà al 100% di sicuro.
Per prima cosa dovrai impostare l'ascoltatore se la tastiera è mostra o nascondi. Se la tastiera è visualizzata, probabilmente l'utente sta digitando, altrimenti digitato.
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
roba è spaventosa imho.
Ho risolto questo problema in questo modo. Ho usato 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.
}
})
Ho avuto lo stesso problema e non volevo fare affidamento sul fatto che l'utente premesse Fine o Invio.
Il mio primo tentativo è stato quello di utilizzare il listener onFocusChange, ma si è verificato che il mio EditText ha ottenuto il focus per impostazione predefinita. Quando l'utente premeva un'altra vista, onFocusChange veniva attivato senza che l'utente gli avesse mai assegnato il focus.
La soluzione successiva l'ha fatto per me, dove è allegato onFocusChange se l'utente ha toccato 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
}
}
}
}
}
Nel mio caso, quando l'utente ha terminato la modifica, è stato eseguito il rendering dello schermo, rinnovando così l'oggetto myEditText. Se lo stesso oggetto viene mantenuto, dovresti probabilmente rimuovere il listener onFocusChange in onFocusChange per prevenire il problema di onFocusChange descritto all'inizio di questo post.
Ho avuto lo stesso problema durante il tentativo di implementare "digitazione in corso" nell'app di chat. prova ad estendere EditText come segue:
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) { }
}
L'ho terminata con lo stesso problema e non potevo usare la soluzione con onEditorAction o onFocusChange e non volevo provare il timer. Un timer è troppo pericoloso perché può avere un sapore, a causa di tutti i thread e troppo imprevedibile, poiché non sai quando il codice viene eseguito.
L'azione onEditorAction non si cattura quando l'utente esce senza utilizzare un pulsante e se lo si utilizza si prega di notare che KeyEvent può essere nullo. Lo stato attivo è inaffidabile ad entrambe le estremità l'utente può ottenere lo stato attivo e uscire senza inserire alcun testo o selezionare il campo e l'utente non deve lasciare l'ultimo campo EditText.
La mia soluzione usa onFocusChange e un flag impostato quando l'utente inizia a modificare il testo e una funzione per ottenere il testo dall'ultima vista focalizzata, che chiamo quando necessario.
Ho solo cancellato il focus su tutti i miei campi di testo per ingannare il codice di visualizzazione del testo di uscita, Il codice clearFocus viene eseguito solo se il campo è attivo. Chiamo la funzione in onSaveInstanceState quindi non devo salvare il flag (mEditing) come stato della vista EditText e quando si fa clic sui pulsanti importanti e quando l'attività è chiusa.
Fai attenzione con TexWatcher poiché è chiamata spesso uso la condizione su focus per non reagire quando il codice onRestoreInstanceState inserisce del testo. io
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();
}
}
Ho fatto qualcosa di simile a questa classe astratta che può essere utilizzata al posto del tipo 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
}
Semplice per attivare la fine della digitazione in EditText
ha funzionato per me, se usi java convertilo
A Kotlin
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}