Ich möchte ein Ereignis abfangen, wenn der Benutzer die Bearbeitung von EditText abgeschlossen hat.
Wie geht das?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Ich möchte ein Ereignis abfangen, wenn der Benutzer die Bearbeitung von EditText abgeschlossen hat.
Wie geht das?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Antworten:
Wenn der Benutzer die Bearbeitung abgeschlossen hat, drückt er Done
oderEnter
((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.
}
}
);
Besser noch, Sie können auch den Listener EditText onFocusChange verwenden, um zu überprüfen, ob der Benutzer die Bearbeitung abgeschlossen hat: (Sie müssen sich nicht darauf verlassen, dass der Benutzer die Taste Fertig oder Eingabetaste auf der Softtastatur drückt. )
((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
}
}
});
Hinweis: Für mehr als einen EditText können Sie auch Ihre Klasse implementieren lassen, View.OnFocusChangeListener
dann die Listener auf jeden von Ihnen EditText setzen und sie wie folgt validieren
((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
. Es wird niemals den Fokus verlieren.
EditText
? Muss ich verwenden onEditorAction
?
EditText
, überprüfen Sie, was der Benutzer tut, um den Bildschirm zu verlassen.
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 }
Obwohl ich etwas eingegeben habe. Dies ist ein Edittext, der nur Zahlen akzeptiert.
Ich persönlich bevorzuge die automatische Übermittlung nach dem Ende der Eingabe. So können Sie dieses Ereignis erkennen.
Erklärungen und Initialisierung:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Listener in zB 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);
}
}
});
Wenn also der Text geändert wird, wartet der Timer auf die nächsten Änderungen. Wenn sie auftreten, wird der Timer abgebrochen und dann erneut gestartet.
Handler
stattdessen
Sie können dies mit setOnKeyListener oder mit einem textWatcher wie dem folgenden tun:
Stellen Sie den Textwächter ein editText.addTextChangedListener(textWatcher);
Dann ruf an
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) {
}
};
Obwohl viele Antworten in die richtige Richtung weisen, denke ich, dass keine von ihnen antwortet, worüber der Autor der Frage nachgedacht hat. Zumindest habe ich die Frage anders verstanden, weil ich nach einer Antwort auf ein ähnliches Problem gesucht habe. Das Problem ist "Wie man erkennt, wann der Benutzer aufhört zu tippen, ohne dass er eine Taste drückt" und eine Aktion auslöst (z. B. automatische Vervollständigung). Wenn Sie dies tun möchten, starten Sie den Timer in onTextChanged mit einer Verzögerung, von der Sie annehmen würden, dass der Benutzer die Eingabe beendet hat (z. B. 500-700 ms), und brechen Sie für jeden neuen Buchstaben beim Starten des Timers den früheren ab (oder verwenden Sie zumindest eine Art von kennzeichnen, dass sie nichts tun, wenn sie ankreuzen). Hier ist ein ähnlicher Code wie der, den ich verwendet habe:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
Beachten Sie, dass ich das laufende boolesche Flag in meiner asynchronen Task ändere (Task ruft den JSON vom Server zur automatischen Vervollständigung ab).
Denken Sie auch daran, dass dies viele Timer-Aufgaben erzeugt (ich denke, sie sind auf demselben Thread geplant, aber Sie müssten dies überprüfen), sodass es wahrscheinlich viele Verbesserungsmöglichkeiten gibt, aber dieser Ansatz funktioniert auch und unter dem Strich sollten Sie dies tun Verwenden Sie einen Timer, da kein Ereignis "Benutzer hat die Eingabe beendet" angezeigt wird.
@Reno und @Vinayak B antworten zusammen, wenn Sie die Tastatur nach der Aktion ausblenden möchten
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
}
}
});
Ein anderer Ansatz ... hier ein Beispiel: Wenn der Benutzer beim Tippen eine Verzögerung von 600-1000 ms hat, können Sie davon ausgehen, dass er gestoppt ist.
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();
}
}
});
Okay, das wird sicher zu 100% funktionieren.
Zuerst müssen Sie den Listener einrichten, wenn die Tastatur ein- oder ausgeblendet ist. Wenn die Tastatur angezeigt wird, tippt der Benutzer wahrscheinlich, andernfalls wird die Eingabe abgeschlossen.
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
Zeug ist beängstigend imho.
Ich habe dieses Problem auf diese Weise gelöst. Ich habe Kotlin benutzt.
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.
}
})
Ich hatte das gleiche Problem und wollte mich nicht darauf verlassen, dass der Benutzer Fertig oder Eingabetaste drückt.
Mein erster Versuch war, den onFocusChange-Listener zu verwenden, aber es kam vor, dass mein EditText standardmäßig den Fokus erhielt. Wenn der Benutzer eine andere Ansicht drückte, wurde der onFocusChange ausgelöst, ohne dass der Benutzer ihm jemals den Fokus zugewiesen hatte.
Die nächste Lösung hat es für mich getan, bei der onFocusChange angehängt wird, wenn der Benutzer den EditText berührt hat:
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
}
}
}
}
}
In meinem Fall wurde der Bildschirm nach dem Bearbeiten des Benutzers erneut gerendert, wodurch das myEditText-Objekt erneuert wurde. Wenn dasselbe Objekt beibehalten wird, sollten Sie wahrscheinlich den onFocusChange-Listener in onFocusChange entfernen, um das zu Beginn dieses Beitrags beschriebene onFocusChange-Problem zu vermeiden.
Ich hatte das gleiche Problem beim Versuch, "Jetzt tippen" in der Chat-App zu implementieren. Versuchen Sie, EditText wie folgt zu erweitern:
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) { }
}}
Ich beendete sie mit dem gleichen Problem und konnte die Lösung nicht mit onEditorAction oder onFocusChange verwenden und wollte den Timer nicht ausprobieren. Ein Timer ist zu gefährlich für den Geschmack, wegen all der Threads und zu unvorhersehbar, da Sie nicht wissen, wann Ihr Code ausgeführt wird.
Die onEditorAction wird nicht abgefangen, wenn der Benutzer ohne Verwendung einer Schaltfläche abreist. Wenn Sie sie verwenden, beachten Sie bitte, dass KeyEvent null sein kann. Der Fokus ist an beiden Enden unzuverlässig. Der Benutzer kann den Fokus erhalten und verlassen, ohne Text einzugeben oder das Feld auszuwählen, und der Benutzer muss das letzte EditText-Feld nicht verlassen.
Meine Lösung verwendet onFocusChange und ein Flag, das gesetzt wird, wenn der Benutzer mit der Bearbeitung von Text beginnt, sowie eine Funktion, um den Text aus der letzten fokussierten Ansicht abzurufen, die ich bei Bedarf aufrufe.
Ich lösche nur den Fokus auf alle meine Textfelder, um den Code für die Textansicht zu verlassen. Der clearFocus-Code wird nur ausgeführt, wenn das Feld den Fokus hat. Ich rufe die Funktion in onSaveInstanceState auf, damit ich das Flag (mEditing) nicht als Status der EditText-Ansicht speichern muss und wenn auf wichtige Schaltflächen geklickt wird und wenn die Aktivität geschlossen wird.
Seien Sie vorsichtig mit TexWatcher, da es häufig aufgerufen wird. Ich verwende die Bedingung auf Fokus, um nicht zu reagieren, wenn der onRestoreInstanceState-Code Text eingibt. ich
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();
}
}
Ich habe so etwas wie diese abstrakte Klasse gemacht, die anstelle des TextView.OnEditorActionListener-Typs verwendet werden kann.
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
}
Einfach auszulösen, um die Eingabe in EditText zu beenden
hat bei mir funktioniert, wenn du Java verwendest, konvertiere es
In Kotlin
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}