Detecting when user has dismissed the soft keyboard
我的视图中有一个EditText小部件。 当用户选择EditText小部件时,我会显示一些指令并显示软键盘。
我使用OnEditorActionListener来检测用户何时完成文本输入,然后关闭键盘,隐藏指令并执行某些操作。
我的问题是当用户按下BACK键关闭键盘时。 操作系统解除键盘,但我的指令(我需要隐藏)仍然可见。
我已经尝试重写OnKeyDown,但是当使用BACK按钮关闭键盘时,似乎没有调用。
我已经尝试在EditText小部件上设置OnKeyListener,但似乎也没有调用。
如何检测软键盘何时被解除?
我知道这样做的方法。对EditText进行子类化并实现:
1 2 3 4 5 6 7 8 | @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { // Do your thing. return true; // So it is not propagated. } return super.dispatchKeyEvent(event); } |
以下是有关如何使用自定义视图的链接(适用于子类EditText时):
http://developer.android.com/guide/topics/ui/custom-components.html
周杰伦,你的解决方案很好!谢谢 :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public class EditTextBackEvent extends EditText { private EditTextImeBackListener mOnImeBack; public EditTextBackEvent(Context context) { super(context); } public EditTextBackEvent(Context context, AttributeSet attrs) { super(context, attrs); } public EditTextBackEvent(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (mOnImeBack != null) mOnImeBack.onImeBack(this, this.getText().toString()); } return super.dispatchKeyEvent(event); } public void setOnEditTextImeBackListener(EditTextImeBackListener listener) { mOnImeBack = listener; } } public interface EditTextImeBackListener { public abstract void onImeBack(EditTextBackEvent ctrl, String text); } |
我通过调用super.onKeyPreIme()对Jay的解决方案稍作改动:
1 2 3 4 5 6 7 8 9 | _e = new EditText(inflater.getContext()) { @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){ cancelTextInput(); } return super.onKeyPreIme(keyCode, event); } }; |
精彩的解决方案,Jay,+ 1!
这是我的自定义EditText,用于检测键盘是否显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /** * Created by TheFinestArtist on 9/24/15. */ public class KeyboardEditText extends EditText { public KeyboardEditText(Context context) { super(context); } public KeyboardEditText(Context context, AttributeSet attrs) { super(context, attrs); } public KeyboardEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(focused, direction, previouslyFocusedRect); if (listener != null) listener.onStateChanged(this, true); } @Override public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (listener != null) listener.onStateChanged(this, false); } return super.onKeyPreIme(keyCode, event); } /** * Keyboard Listener */ KeyboardListener listener; public void setOnKeyboardListener(KeyboardListener listener) { this.listener = listener; } public interface KeyboardListener { void onStateChanged(KeyboardEditText keyboardEditText, boolean showing); } } |
现在是2019年......
所以我用Kotlin创建了一个更整洁的解决方案
1.创建扩展功能:
1 2 3 4 5 6 7 8 | fun Activity.addKeyboardToggleListener(onKeyboardToggleAction: (shown: Boolean) -> Unit): KeyboardToggleListener? { val root = findViewById<View>(android.R.id.content) val listener = KeyboardToggleListener(root, onKeyboardToggleAction) return root?.viewTreeObserver?.run { addOnGlobalLayoutListener(listener) listener } } |
2.切换监听器是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class KeyboardToggleListener( private val root: View?, private val onKeyboardToggleAction: (shown: Boolean) -> Unit ) : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { root?.run { val heightDiff = rootView.height - height val keyboardShown = heightDiff > dpToPx(200f) onKeyboardToggleAction.invoke(keyboardShown) } } } fun View.dpToPx(dp: Float) = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics).roundToInt() |
3.在任何活动中使用它就像这样简单:
1 2 3 | addKeyboardToggleListener {shown -> // hurray! Now you know when the keyboard is shown and hidden!! } |
只需创建一个扩展Edittext的类,并在代码中使用该edittext,
您应该在自定义edittext中覆盖以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 | @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { //Here it catch all back keys //Now you can do what you want. } else if (keyCode == KeyEvent.KEYCODE_MENU) { // Eat the event return true; } return false;} |
这是关键监听器的解决方案。
我不知道为什么这样可行,但如果您只是纯粹覆盖自定义EditText上的onKeyPreIme,则OnKeyListener可以正常工作。
SomeClass.java
1 2 3 4 5 6 7 8 9 10 | customEditText.setOnKeyListener((v, keyCode, event) -> { if(event.getAction() == KeyEvent.ACTION_DOWN) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: getPresenter().onBackPressed(); break; } } return false; }); |
CustomEditText.java
1 2 3 4 | @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { return super.dispatchKeyEvent(event); } |
使用@ olivier_sdg的答案,但转换为Kotlin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class KeyboardEditText : EditText { private var mOnImeBack: EditTextImeBackListener? = null constructor(context: Context) : super(context) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean { if (event.keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { if (mOnImeBack != null) mOnImeBack!!.onImeBack(this, this.text.toString()) } return super.dispatchKeyEvent(event) } fun setOnEditTextImeBackListener(listener: EditTextImeBackListener) { mOnImeBack = listener } } interface EditTextImeBackListener { fun onImeBack(ctrl: KeyboardEditText, text: String) } |
键盘关闭时,
1 2 3 4 5 6 | InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.hideSoftInputFromWindow(findFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS)) { //keyboard is closed now do what you need here } |
对于那些希望在Xamarin中做同样事情的人,我已经翻译了一些顶级答案,因为它有点不同。我在这里创建了一个要点,但总结一下,你创建一个自定义的EditText并覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class CustomEditText : EditText { public event EventHandler BackPressed; // ... public override bool OnKeyPreIme([GeneratedEnum] Keycode keyCode, KeyEvent e) { if (e.KeyCode == Keycode.Back && e.Action == KeyEventActions.Up) { BackPressed?.Invoke(this, new EventArgs()); } return base.OnKeyPreIme(keyCode, e); } } |
......然后在视图中......
1 2 3 4 5 | editText = FindViewById<CustomEditText>(Resource.Id.MyEditText); editText.BackPressed += (s, e) => { // <insert code here> }; |