Detecting when user has dismissed the soft keyboar

2020-01-24 06:20发布

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

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.

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.

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

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

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

标签: android
10条回答
Explosion°爆炸
2楼-- · 2020-01-24 07:07

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

1.Create an extension function:

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:

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.Use it in any Activity as simple as this:

addKeyboardToggleListener {shown ->
          // hurray! Now you know when the keyboard is shown and hidden!!
      }
查看更多
混吃等死
3楼-- · 2020-01-24 07:10

Using @olivier_sdg's answer, but converted to 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)
}
查看更多
够拽才男人
4楼-- · 2020-01-24 07:16

hideSoftInputFromWindow returns true when keyboard closes use it's value to detect keyboard close in 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
        }
查看更多
地球回转人心会变
5楼-- · 2020-01-24 07:17

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

@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

查看更多
登录 后发表回答