android EditText-завершенное событие ввода


Я хочу поймать событие, когда пользователь заканчивает редактирование EditText.

Как это можно сделать?

12 89

12 ответов:

когда пользователь закончит редактирование, он / она нажмет 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 listener, чтобы проверить, сделал ли пользователь редактирование:(не нужно полагаться на пользователя нажав кнопку Готово или клавишу Enter на клавиатуре)

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

        }
    };

оба @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
        }
    }
});

хотя многие ответы указывают в правильном направлении, я думаю, что ни один из них не отвечает на то, о чем думал автор вопроса. Или, по крайней мере, я понял вопрос по-другому, потому что я искал ответ на подобную проблему. Проблема заключается в том, "как узнать, когда пользователь перестает печатать, не нажимая на кнопку" и вызвать некоторое действие (например, автозаполнение). Если вы хотите сделать это, запустите таймер в onTextChanged с задержкой, которую вы считаете остановленной пользователем набрав (например, 500-700ms), для каждой новой буквы при запуске таймера отмените предыдущую (или, по крайней мере, используйте какой-то флаг, который, когда они тикают, они ничего не делают). Вот аналогичный код, что я использовал:

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

обратите внимание, что я изменяю запуск логического флага внутри моей асинхронной задачи (Задача получает json с сервера для автоматического завершения).

также имейте в виду, что это создает много задач таймер (я думаю, что они запланированы на том же потоке, но ты бы нужно проверить это), поэтому, вероятно, есть много мест для улучшения, но этот подход также работает, и суть в том, что вы должны использовать таймер, поскольку нет "пользователь перестал печатать событие"

хорошо это будет работать 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();
                }
            }
        });

У меня была та же проблема, и я не хотел полагаться на то, что пользователь нажмет кнопку "Готово" или "ввод".

моя первая попытка была использовать 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 может быть null. Фокус ненадежен на обоих концах пользователь может получить сфокусируйтесь и оставьте без ввода текста или выбора поля, и пользователю не нужно оставлять последнее поле EditText.

мое решение использует onFocusChange и флаг, установленный, когда пользователь начинает редактировать текст и функцию, чтобы получить текст из последнего сфокусированного представления, которое я вызываю, когда это необходимо.

Я просто очищаю фокус на всех моих текстовых полях, чтобы обмануть код просмотра текста leave, код clearFocus выполняется только в том случае, если поле имеет фокус. Я называю эту функцию в onSaveInstanceState поэтому мне не нужно сохранять флаг (mEditing) как состояние представления EditText и когда нажимаются важные кнопки и когда действие закрыто.

будьте осторожны с TexWatcher, как это вызов часто я использую условие на фокус, чтобы не реагировать, когда onrestoreinstancestate код ввода текста. Я

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
}