Я хочу поймать событие, когда пользователь закончит редактирование EditText.
Как это можно сделать?
Я хочу поймать событие, когда пользователь закончит редактирование EditText.
Как это можно сделать?
Когда пользователь закончит редактирование, он нажмет Done
или 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.
}
}
);
Лучше, вы также можете использовать прослушиватель EditText onFocusChange, чтобы проверить, выполнил ли пользователь редактирование: (Не нужно полагаться на пользователя, нажимая кнопку "Готово" или "Enter" на Softkey)
((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);
}
}
});
Я лично предпочитаю автоматический прием после окончания ввода. Здесь вы можете обнаружить это событие.
Объявления и инициализация:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Приемник, например. 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);
}
}
});
Таким образом, при изменении текста таймер начинает ждать, пока произойдут какие-либо последующие изменения. Когда они происходят, таймер отменяется, а затем запускается еще раз.
Вы можете сделать это с помощью setOnKeyListener или с помощью textWatcher, например:
Установить наблюдателя текста editText.addTextChangedListener(textWatcher);
затем вызовите
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) {
}
};
Хотя многие ответы указывают на правильное направление, я думаю, что ни один из них не отвечает на вопрос, о чем думал автор вопроса. Или, по крайней мере, я понял вопрос по-другому, потому что искал ответ на подобную проблему. Проблема заключается в том, "Как узнать, когда пользователь перестает набирать текст без нажатия кнопки" и запускает какое-либо действие (например, автозаполнение). Если вы хотите сделать это, запустите таймер в onTextChanged с задержкой, которую вы считаете пользователем остановленной набирать (например, 500-700 мс), для каждой новой буквы при запуске таймера отменить предыдущий (или, по крайней мере, использовать какой-то флаг, что когда они гасят, они ничего не делают). Вот аналогичный код, который я использовал:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
Обратите внимание, что я изменяю запуск булевого флага внутри моей задачи async (задача получает json с сервера для автоматического заполнения).
Также имейте в виду, что это создает много задач таймера (я думаю, что они запланированы в той же теме, но вам нужно будет это проверить), поэтому, вероятно, есть много возможностей для улучшения, но этот подход также работает, а нижняя строка что вы должны использовать таймер, так как нет "Пользователь прекратил печатать событие"
оба @Reno и @Vinayak B отвечают вместе, если вы хотите скрыть клавиатуру после действия
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
}
}
});
Хорошо, это будет работать на 100%.
Сначала вам нужно настроить прослушиватель, если клавиатура отображается или скрывается. Если клавиатура показывается, то, вероятно, пользователь печатает, в противном случае делается ввод.
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;
}
}
}
});
Другой подход... вот пример: Если у пользователя есть задержка в 600-1000 мс при вводе, вы можете считать, что он остановился.
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();
}
}
});
У меня была такая же проблема, и я не хотел полагаться на пользователя, нажимая "Готово" или "Enter".
Моя первая попытка состояла в том, чтобы использовать прослушиватель onFocusChange, но произошло, что мой EditText получил фокус по умолчанию. Когда пользователь нажал какое-то другое представление, функция onFocusChange была запущена без того, чтобы пользователь не назначил ему фокус.
Следующее решение сделало это для меня, где onFocusChange присоединяется, если пользователь коснулся 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
}
}
}
}
}
В моем случае, когда пользователь был сделан, редактирование экрана было отменено, тем самым обновив объект myEditText. Если один и тот же объект сохранен, вероятно, вы должны удалить прослушиватель onFocusChange в onFocusChange, чтобы предотвратить проблему onFocusChange, описанную в начале этого сообщения.
У меня была такая же проблема при попытке реализовать "теперь печатать" в приложении чата. попробуйте расширить EditText следующим образом:
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) { }
}
Я закончил ее с той же проблемой, и я не мог использовать решение с onEditorAction или onFocusChange и не хотел попробовать таймер. Таймер слишком опасен для вкуса, потому что все потоки и слишком непредсказуемы, так как вы не знаете, когда вы выполняете код.
OnEditorAction не улавливается, когда пользователь уходит без использования кнопки, и если вы используете его, обратите внимание, что KeyEvent может быть нулевым. Фокус ненадежен с обоих концов, пользователь может получить фокус и оставить без ввода какого-либо текста или выбора поля, и пользователю не нужно оставлять последнее поле EditText.
Мое решение использует onFocusChange и флаг, установленный, когда пользователь начинает редактировать текст и функцию, чтобы получить текст из последнего сфокусированного представления, которое я вызываю при необходимости.
Я просто очищаю фокус на всех моих текстовых полях, чтобы обмануть код просмотра текста отпуска. Код clearFocus выполняется только в том случае, если в поле есть фокус. Я вызываю функцию в onSaveInstanceState, поэтому мне не нужно сохранять флаг (mEditing) в качестве состояния вида EditText и когда нажимаются важные кнопки и когда активность закрывается.
Будьте осторожны с TexWatcher, так как он часто звонит, я использую условие фокуса, чтобы не реагировать, когда код onRestoreInstanceState вводит текст. I
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();
}
}
Я сделал что-то вроде этого абстрактного класса, который можно использовать вместо типа 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
}
Простой, чтобы закончить печатать в EditText
работал для меня, если вы используете Java конвертировать его
В Котлине
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}