webentwicklung-frage-antwort-db.com.de

android EditText - Eingabe abgeschlossen

Ich möchte ein Ereignis abfangen, wenn der Benutzer EditText bearbeitet hat.

Wie geht das?

93
eddyuk

Wenn der Benutzer die Bearbeitung abgeschlossen hat, drückt er auf Done oder 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. 
        }
    }
);
103
Reno

Besser können Sie auch den EditText-Listener onFocusChange verwenden, um zu prüfen, ob der Benutzer die Bearbeitung vorgenommen hat: (Sie müssen sich nicht darauf verlassen, dass der Benutzer die Done- oder Enter-Taste auf der Soft-Tastatur 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) {
       validateInput(v);
      }
    }
 });
160

Ich persönlich bevorzuge das automatische Senden nach dem Ende der Eingabe. So können Sie dieses Ereignis erkennen.

Deklarationen und Initialisierung:

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

Hörer in z. 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 der Text geändert wird, wartet der Timer also auf die nächsten Änderungen. Wenn sie auftreten, wird der Timer abgebrochen und dann erneut gestartet.

45
ZimaXXX

Sie können dies mit setOnKeyListener oder mit einem textWatcher wie folgt tun:

Text-Watcher einstellen 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) {

        }
    };
19
ShineDown

@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
        }
    }
});
4
Tyler Davis

Obwohl viele Antworten in die richtige Richtung weisen, denke ich, dass keine von ihnen das beantwortet, worüber der Autor der Frage nachgedacht hat. Oder zumindest habe ich die Frage anders verstanden, weil ich auf ähnliche Probleme eine Antwort suchte. Das Problem ist "Wie kann ich wissen, wann der Benutzer die Eingabe abbricht, ohne dass er eine Taste drückt" und eine Aktion auslöst (z. B. Auto-Completion). Wenn Sie dies tun möchten, starten Sie den Timer in onTextChanged mit einer Verzögerung, die der Benutzer möglicherweise nicht mehr eingibt (z. B. 500-700ms), und stornieren Sie für jeden neuen Buchstaben beim Start des Timers den vorherigen (oder verwenden Sie mindestens eine Art von kennzeichnen Sie, dass, wenn sie ticken, sie nichts tun). Hier ist ein ähnlicher Code zu dem, was ich verwendet habe:

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

Beachten Sie, dass ich die Ausführung des booleschen Flags in meiner asynchronen Task verändere (Task erhält den Json vom Server für die automatische Vervollständigung).

Bedenken Sie auch, dass dadurch viele Timer-Aufgaben erstellt werden (ich denke, sie sind im selben Thread geplant, aber Sie müssten dies überprüfen). Es gibt wahrscheinlich viele Stellen, an denen Sie sich verbessern können, aber dieser Ansatz funktioniert auch und im Endeffekt sollten Sie dies tun Verwenden Sie einen Timer, da es kein "Ereignis zum Abbruch der Eingabe des Benutzers" gibt.

4
PSIXO

Ein anderer Ansatz ... hier ist ein Beispiel: Wenn der Benutzer beim Tippen eine Verzögerung von 600-1000 ms hat, kann dies als gestoppt angesehen werden.

 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();
                }
            }
        });

2
ChristianMEC

Okay, das wird sicher 100% funktionieren.

Zuerst müssen Sie den Listener einrichten, wenn die Tastatur ein- oder ausgeblendet ist .. Wenn die Tastatur angezeigt wird, tippt wahrscheinlich der Benutzer, andernfalls erfolgt die Eingabe.

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;
                        }
                    }
            }
        });
2
Krit

Ich habe 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
}
0
Michał Ziobro

Ich hatte das gleiche Problem und wollte mich nicht darauf verlassen, dass der Benutzer Done oder Enter drückt. 

Mein erster Versuch bestand darin, den onFocusChange-Listener zu verwenden, es kam jedoch 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 gemacht, wo der onFocusChange angehängt wird, wenn der Benutzer den EditText berührt:

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 am Anfang dieses Beitrags beschriebene onFocusChange-Problem zu vermeiden.

0
Jos

Ich hatte das gleiche Problem, als ich versuchte, "Jetzt eingeben" in der Chat-App zu implementieren. Bearbeiten Sie EditText wie folgt:

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

}

0
Nadav

Ich beendete sie mit demselben 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, da alle Threads zu unvorhersehbar sind, da Sie nicht wissen, wann der Code ausgeführt wird.

Die onEditorAction fängt nicht ab, wenn der Benutzer ohne die Verwendung einer Schaltfläche abbricht. Wenn Sie sie verwenden, beachten Sie, dass KeyEvent NULL sein kann. Der Fokus ist an beiden Enden unzuverlässig. Der Benutzer kann den Fokus erhalten und verlassen, ohne Text eingeben oder das Feld auswählen zu müssen. 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 und einer Funktion beginnt, um den Text aus der letzten fokussierten Ansicht abzurufen, die ich bei Bedarf anrufe.

Ich lösche einfach den Fokus auf allen meinen Textfeldern, um den Code für die Textansicht für das Ablesen zu markieren. Der clearFocus-Code wird nur ausgeführt, wenn das Feld den Fokus hat. Ich rufe die Funktion in onSaveInstanceState auf, sodass ich das Flag (mEditing) nicht als Status der EditText-Ansicht speichern muss, wenn wichtige Schaltflächen angeklickt werden und die Aktivität geschlossen wird. 

Seien Sie vorsichtig mit TexWatcher, da es oft aufgerufen wird. Ich verwende die Bedingung für den Fokus, um nicht zu reagieren, wenn der Code onRestoreInstanceState in den Text eingeht 

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();
    }
}
0
Rezder