android 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.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { if (!event.isShiftPressed()) { // the user is done typing. return true; // consume. } } return false; // pass on to other listeners. } });
更好的方法是,您还可以使用EditText onFocusChange侦听器来检查用户是否已经完成编辑:( 不需要依靠用户按下软键盘上的完成或inputbutton)
((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); } } });
我个人更喜欢在input结束后自动提交。 以下是如何检测此事件。
声明和初始化:
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 } } });
虽然很多答案都指向了正确的方向,但我认为他们都没有回答这个问题的作者在想什么。 或者至less我对这个问题有不同的理解,因为我正在寻找类似问题的答案。 问题是“如何知道用户什么时候停止键入,而不需要按下button”,并触发一些操作(例如自动完成)。 如果你想这样做,启动计时器在onTextChanged延迟,你会认为用户停止input(例如500-700毫秒),每个新的字母,当你启动定时器取消较早的一个(或至less使用某种标记,当他们打勾他们什么都不做)。 这里是我用过的代码:
new Timer().schedule(new TimerTask() { @Override public void run() { if (!running) { new DoPost().execute(s.toString()); }); } }, 700);
请注意,我修改了我的asynchronous任务中的运行布尔标志(任务获取从服务器的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(); } } });
我有同样的问题,并不想依靠用户按下完成或input。
我第一次尝试使用onFocusChange侦听器,但它发生,我的EditText默认获得焦点。 当用户按下其他视图时,onFocusChange被触发,而用户从未分配焦点。
下一个解决scheme为我做了,如果用户触摸EditText附加onFocusChange:
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问题。
在尝试在聊天应用上实现“正在input”时,我遇到了同样的问题。 尝试扩展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的解决scheme,并不想尝试计时器。 一个定时器太危险了,因为所有的线程和太不可预知的东西,因为你不知道什么时候你的代码被执行。
当用户不使用button离开onEditorAction时,如果使用它,请注意KeyEvent可以为null。 重点是不可靠的两端用户可以得到的焦点和离开而不input任何文字或select字段和用户不需要离开最后EditText字段。
我的解决scheme使用onFocusChange和用户开始编辑文本时设置的标志,以及从最后一个聚焦视图中获取文本的function,我需要时调用。
我只是清除了所有文本字段上的焦点,以避开离开文本视图代码。只有当字段具有焦点时,才会执行clearFocus代码。 我在onSaveInstanceState中调用函数,因此我不必将标志(mEditing)保存为EditText视图的状态,并且当重要的button被单击并且活动被closures时。
小心TexWatcher,因为它是经常调用我使用的焦点条件,当onRestoreInstanceState代码input文本时不反应。 一世
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(); } }