Richard
Richard

Reputation: 7433

Cleaner way to maintain virtual keyboard on orientation change

I have the following EditText in my XML:

<EditText
  android:id="@+id/searchField"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:hint="What do you want to eat?"
  android:imeOptions="actionSearch"
  android:inputType="text"
  android:maxLines="1"
  ... />

On orientation change, I will record the focused state of the EditText, searchField. I record this state using override fun onSaveInstanceState(...) like below:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putBoolean("SEARCH_FOCUSED", searchField.hasFocus())
}

If searchField.hasFocus() is equal to true, I want the virtual keyboard to be showed when device orientation changes. To do that, I set this on my override fun onRestoreInstaceState(...) like below:

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    val searchFocused = savedInstanceState.getBoolean("SEARCH_FOCUSED")
    if (searchFocused) {
        searchField.requestFocus()
        searchField.postDelayed({ imm.showSoftInput(searchField,
            SHOW_FORCED)
        }, 200)
    }
}

The above works.

Concern #1

However, the above way is not ideal. I had to set a postDelayed(Runnable, time) to make the virtual keyboard appear, which doesn't seem like the best solution to me. Ideally, I want to be able to simply do the following. The problem, though, with the below code is that the keyboard does not show at all on orientation change.

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    val searchFocused = savedInstanceState.getBoolean("SEARCH_FOCUSED")
    if (searchFocused) {
        searchField.requestFocus()
        imm.showSoftInput(searchField, SHOW_FORCED)
    }
}

Concern #2

Furthermore, notice that I used SHOW_FORCED instead of SHOW_IMPLICIT. This is really bad because when I tap on my home button (the Activity is now onStop()), the keyboard is still visible. I know this is due to SHOW_FORCED indicating that the keyboard must be hidden explicitly by the user him/herself. Ideally, I want to use SHOW_IMPLICIT. The problem with using SHOW_IMPLICIT is that the keyboard does not appear on landscape orientation, but does appear on portrait orientation.

So, my questions are:

Upvotes: 2

Views: 196

Answers (1)

quealegriamasalegre
quealegriamasalegre

Reputation: 3258

I have read about this issue on other threads.

here is a suggestion that i think is worth trying out:

(this will be in java as i dont speak kotlin, sorry)

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
    if (hasFocus) {
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    }else{
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);}
    }
});

this way the input method should be shown whenever focus is granted to the edittext. you might have to make sure that your edittext doesnt have focus on activity creation though. let me know it this works and if it addresses both (or any) of your concerns.

Upvotes: 2

Related Questions