2

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:

  • Why can't I immediately set imm.showSoftInput(...) without using postDelayed(...) for the virtual keyboard to show? Am I missing some other prerequisite steps in using showSoftInput?
  • How can I use SHOW_IMPLICIT to make sure that the keyboard is hidden automatically when the Activity is in the background (onPause()/onStop())?
Amir Hossein
  • 319
  • 2
  • 14
Richard
  • 7,037
  • 2
  • 23
  • 76

1 Answers1

2

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.

quealegriamasalegre
  • 2,887
  • 1
  • 13
  • 35
  • Could you also explain why this workaround might work and answer my two questions directly ;-)? I'm still curious as to why my initial intention isn't working. – Richard Apr 20 '20 at 04:38
  • I mean for sure, i dont know why your code requires the post delayed but i have a hunch: searchField.requestFocus() is not actually giving focus to your edit text but merely requesting it so your post delayed is simply artificially waiting until said focus has actually been granted. with my approach I guess you would be doing it the "right way" and displaying the keyboard immediately once the edittext has gained focus (this should all happen in a split second anyway) – quealegriamasalegre Apr 20 '20 at 04:54
  • on your second concern i read here https://stackoverflow.com/a/10420979/10637400 that getWindow().setSoftInputMode(...) is more reliable than InputMethodManager to make the keyboard appear so i went for that. have you actually tested the code? cause i didnt – quealegriamasalegre Apr 20 '20 at 04:58
  • I have not tried out your solution. Will do when I have time. I'm curious as to why it's `getWindow().setSoftInput(...)` is more reliable though. – Richard Apr 20 '20 at 05:34
  • To your hunch *`searchField.requestFocus()` is not actually giving focus to your edit text but merely requesting it so your post delayed is simply artificially waiting until said focus has actually been granted*, I'd like to point out that you don't have to focus on an `EditText` to show a virtual keyboard (e.g. clicking a button). As a result, I see no problem with the `EditText` not gaining focus before showing the virtual keyboard. Or is there? – Richard Apr 20 '20 at 05:35
  • frankly i dont know, i mean it would make sense for there to be something editable in focus before you show a keyboard but i have also seen it being displayed after the editable part has disappeared. however it seems suspicious that you need to add a delay for it to work in your code. to me this signals that something has to happen before you are able to display a keyboard. have you tried shortening the delay until sometimes it doesnt work? maybe explore a bit in the logcat – quealegriamasalegre Apr 20 '20 at 05:52
  • **Update**. Sorry I haven't been experimenting with this, but I've finally tried some things and I wanted to tell you something. First, when I set `postDelayed` with a very small delay such as `10ms`, the solution in my question does not work. Second, your solution works perfectly. Your solution hides the keyboard on orientation change, **hides** the keyboard when I tap my phone's home button (caused by `SHOW_FORCED`), **and** shows the keyboard if the `editText` has focus and the orientation is changed to landscape (which I had to solve using `SHOW_FORCED`). – Richard May 19 '20 at 08:24
  • Your solution worked well (thank you for that!). I was wondering where I can read more about how you got to that solution and how you concluded that my solution (IMM) is less reliable (the link you provided did not provide an explanation). – Richard May 19 '20 at 08:25
  • I've also tested further and it shows the correct `inputMethod` specified on the `EditText`. – Richard May 19 '20 at 08:31
  • I mean from the comments here https://stackoverflow.com/a/10420979/10637400 you can infer that apparently IMM wont work propperly on older android versions (4.4.2 for instance). but I actually dont know it exactly. I just took it at face value to be totally honest. – quealegriamasalegre May 19 '20 at 18:02