我的视图中有一个EditText小部件。当用户选择EditText小部件时,我会显示一些指令并显示软键盘。
我使用OnEditorActionListener来检测用户何时完成文本输入并关闭键盘,隐藏指令并执行某些操作。
我的问题是当用户按BACK键取消键盘时。操作系统取消键盘,但我的指令(我需要隐藏)仍然可见。
我已经尝试重写OnKeyDown,但是当使用BACK按钮关闭键盘时,似乎没有调用它。
我已尝试在EditText小部件上设置OnKeyListener,但似乎也没有调用。
如何检测软键盘何时被解除?
答案 0 :(得分:156)
我知道这样做的方法。对EditText进行子类化并实现:
@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 :(得分:115)
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);
}
答案 2 :(得分:17)
我通过调用super.onKeyPreIme()对Jay的解决方案稍作改动:
_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!
答案 3 :(得分:12)
这是我的自定义EditText,用于检测键盘是否显示
/**
* 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);
}
}
答案 4 :(得分:4)
只需创建一个扩展Edittext并在代码中使用该edittext的类, 您应该只在自定义edittext中覆盖以下方法:
@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;}
答案 5 :(得分:2)
这是关键监听器的解决方案。 我不知道为什么会这样,但如果你纯粹在自定义的EditText上覆盖onKeyPreIme,OnKeyListener就可以工作。
SomeClass.java
customEditText.setOnKeyListener((v, keyCode, event) -> {
if(event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
getPresenter().onBackPressed();
break;
}
}
return false;
});
CustomEditText.java
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
return super.dispatchKeyEvent(event);
}
答案 6 :(得分:2)
现在是2019年...
所以我用Kotlin创建了一个更简洁的解决方案
1。创建扩展功能:
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。切换侦听器在哪里:
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. 在以下任何活动中使用它:
addKeyboardToggleListener {shown ->
// hurray! Now you know when the keyboard is shown and hidden!!
}
答案 7 :(得分:1)
使用@ olivier_sdg的答案,但转换为Kotlin:
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)
}
答案 8 :(得分:0)
对于那些希望在Xamarin中做同样事情的人,我已经翻译了一些顶级答案,因为它有点不同。我创建了一个要点here,但总结一下,您创建了一个自定义的EditText并覆盖OnKeyPreIme
,如下所示:
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);
}
}
...然后在视图中......
editText = FindViewById<CustomEditText>(Resource.Id.MyEditText);
editText.BackPressed += (s, e) =>
{
// <insert code here>
};
答案 9 :(得分:0)
hideSoftInputFromWindow
在键盘关闭时返回true,使用它的值检测android中的键盘关闭
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
}