Android 检测用户何时关闭软键盘

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3425932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:09:12  来源:igfitidea点击:

Detecting when user has dismissed the soft keyboard

android

提问by deSelby

I have an EditText widget in my view. When the user selects the EditText widget, I display some instructions and the soft keyboard appears.

我的视图中有一个 EditText 小部件。当用户选择 EditText 小部件时,我会显示一些说明并出现软键盘。

I use an OnEditorActionListener to detect when the user has completed text entry and I dismiss the keyboard, hide the instructions and perform some action.

我使用 OnEditorActionListener 来检测用户何时完成文本输入,然后关闭键盘、隐藏指令并执行一些操作。

My problem is when the user dismisses the keyboard by pressing the BACK key. The OS dismisses the keyboard, but my instructions (which I need to hide) are still visible.

我的问题是当用户通过按 BACK 键关闭键盘时。操作系统关闭键盘,但我的指令(我需要隐藏)仍然可见。

I've tried overriding OnKeyDown, but that doesn't seem to get called when the BACK button is used to dismiss the keyboard.

我试过覆盖 OnKeyDown,但是当使用 BACK 按钮关闭键盘时,它似乎没有被调用。

I've tried setting an OnKeyListener on the EditText widget, but that doesn't seem to get called either.

我试过在 EditText 小部件上设置 OnKeyListener ,但似乎也没有被调用。

How can I detect when the soft keyboard is being dismissed?

如何检测软键盘何时被关闭?

回答by Jay

I know a way to do this. Subclass the EditText and implement:

我知道一种方法来做到这一点。子类化 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);
}

Here is a link on how to use your custom views (for when you subclass EditText): http://developer.android.com/guide/topics/ui/custom-components.html

以下是有关如何使用自定义视图的链接(用于子类 EditText 时):http: //developer.android.com/guide/topics/ui/custom-components.html

回答by olivier_sdg

Jay, your solution is good ! thanks :)

杰伊,你的解决方案很好!谢谢 :)

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);
}

回答by Steelight

I made a slight change on Jay's solution by calling super.onKeyPreIme():

我通过调用 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);
    }
};

Wonderful solution, Jay, +1!

绝妙的解决方案,杰,+1!

回答by The Finest Artist

Here is my custom EditText to detect whether keyboard is showing or not

这是我的自定义 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);
    }
}

回答by Leo Droidcoder

It's 2019 now...
So I created a more neat solution with Kotlin

现在是 2019 年......
所以我用 Kotlin 创建了一个更简洁的解决方案

1.Create an extension function:

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.Where the toggle listener is:

2.切换监听器在哪里:

open class KeyboardToggleListener(
        private val root: View?,
        private val onKeyboardToggleAction: (shown: Boolean) -> Unit
) : ViewTreeObserver.OnGlobalLayoutListener {
    private var shown = false
    override fun onGlobalLayout() {
        root?.run {
            val heightDiff = rootView.height - height
            val keyboardShown = heightDiff > dpToPx(200f)
            if (shown != keyboardShown) {
                onKeyboardToggleAction.invoke(keyboardShown)
                shown = keyboardShown
            }
        }
    }
}

fun View.dpToPx(dp: Float) = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics).roundToInt()

3.Use it in any Activity as simple as this:

3.在任何活动中使用它就像这样简单

addKeyboardToggleListener {shown ->
          // hurray! Now you know when the keyboard is shown and hidden!!
      }

回答by farhad.kargaran

Just create a class that extends Edittext and use that edittext in your code, you should just override the following method in the custom edittext:

只需创建一个扩展 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;}

回答by Rubin Yoo

Here's a solution with the key listener. I have no idea why this works but OnKeyListener works if you just purely override onKeyPreIme on your custom EditText.

这是带有关键侦听器的解决方案。我不知道为什么会这样,但是 OnKeyListener 可以工作,如果你只是在你的自定义 EditText 上纯粹覆盖 onKeyPreIme。

SomeClass.java

类.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);
    }

回答by Steven Evers

For anyone looking to do the same in Xamarin, I've translated some of the top answers as it's a bit different. I created a gist herebut summarizing, you create a custom EditText and override OnKeyPreImelike so:

对于希望在 Xamarin 中做同样事情的人,我已经翻译了一些最重要的答案,因为它有点不同。我在这里创建了一个要点但总结一下,您创建了一个自定义 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);
    }
}

... and then in the view...

......然后在视图中......

editText = FindViewById<CustomEditText>(Resource.Id.MyEditText);
editText.BackPressed += (s, e) => 
{
    // <insert code here>
};

回答by bmjohns

Using @olivier_sdg's answer, but converted to Kotlin:

使用@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)
}

回答by Bali

hideSoftInputFromWindowreturns true when keyboard closes use it's value to detect keyboard close in android

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
        }