androidkotlinautocompletetextviewmaterial-components-androidandroid-textinputlayout

Hide Soft Keyboard When User Touches the Dropdown Menu


I have the following Android Material Components exposed drop-down menu in my app:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/drop_down_menu"
    style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_marginEnd="8dp"
    android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar"
    app:boxBackgroundColor="@android:color/white"
    app:layout_constraintBottom_toBottomOf="@+id/number_text_view"
    app:layout_constraintEnd_toStartOf="@+id/add_button"
    app:layout_constraintTop_toTopOf="@+id/number_text_view">

    <com.google.android.material.textfield.MaterialAutoCompleteTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="none"
        android:paddingStart="8dp"
        android:paddingEnd="8dp" />
</com.google.android.material.textfield.TextInputLayout>

How do I hide the soft keyboard in my fragment when the user touches the drop-down menu and the menu options appear? The keyboard shows when the user clicks on the EditText component and doesn't touch another part of the screen before touching the drop-down menu to close the keyboard.


Solution

  • You can register focusChangeListener to the MaterialAutoCompleteTextView and hide the keyboard when it gained the focus.

    autoCompleteTextView.setOnFocusChangeListener { v, hasFocus ->
        if (hasFocus) {
            hideSoftKeyboard() // Using activity extension function
            // v.hideKeyboard() // Using view extension function
        }
    }
    

    And here is Activity extension function to hide the keyboard:

    fun Activity.hideSoftKeyboard() {
        val inputMethodManager =
            this.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
        val currentFocus = this.currentFocus
        val windowToken = this.window?.decorView?.rootView?.windowToken
        inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
        inputMethodManager.hideSoftInputFromWindow(
            windowToken,
            InputMethodManager.HIDE_NOT_ALWAYS
        )
        if (currentFocus != null) {
            inputMethodManager.hideSoftInputFromWindow(currentFocus.windowToken, 0)
        }
    }
    

    Or you can use the below on the View itself. Source

    fun View.hideKeyboard(): Boolean {
        try {
            val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            return inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
        } catch (ignored: RuntimeException) { }
            return false
        }
    }