Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maintain keyboard open/closed state for EditText when app comes to foreground

I have an Activity which is recreated on a config change (desired). I have a DialogFragment which calls setRetainInstance(true) with a single EditText in its layout.

In the DialogFragment's onActivityCreated I call:

getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 

A) If I open the keyboard then when I put the app into the background and then bring it to the foregournd then I want the keyboard to still be displayed.

B) If I close the keyboard (EditText still has focus and shows cursor which is desired behaviour) then I want the keyboard to still be closed if I put the app into the background and then bring it to the foreground.

I can't seem to achieve both A) and B). The keyboard is always closed when I bring the app to the foreground. I've tried .SOFT_INPUT_STATE_ALWAYS_VISIBLE but then the keyboard is always open.

Thanks in advance for any suggestions as to how I might achieve this. I also wish to maintain such keyboard state across rotation but I'm leaving that for another day. Peter.

Edit Please note that I do not want to prevent the activity from being re-created on a configuration change.

I also experimented with WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED which did maintain the keyboard open/close state during rotation on a phone (single pane layout) but a) did not work with a dual pane layout b) did not maintain the keyboard state when bringing the app to the foreground.

like image 433
PJL Avatar asked Mar 04 '13 13:03

PJL


People also ask

How do I hide the soft keyboard on Android after clicking outside Edittext?

and put the following code in the onTouch method. InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm. hideSoftInputFromWindow(getCurrentFocus(). getWindowToken(), 0);


2 Answers

Hello first of all thanks for an interesting question. It made me experiment with code. Here I am describing my solution.

To find the solution I had to know two things

1. how to detect whether a softkeyboard is visible or not

2. How to set softkeyboard visible or hidden.

I got the solution in the following steps after searching a bit I realized that the best solution of detecting a softkeyboardstate (visible/hidden) is to use ViewTreeObserver. I am directly pointing to a so answer to know about it if you don't know. Here is the link.

and to set the softkeyboardstate I just used Window.setSoftInputMode method.

and to know a user interaction I override onUserInteraction method

Kept two flag. one flag is to preserve keyboardstate another is to know whether the application went to background or not

CODE:

1. variable declared

int lastDiff = 0; volatile boolean flag = false; volatile int flag2 = 0; 

2. ViewTreeObserver

activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(     new OnGlobalLayoutListener() {         @Override         public void onGlobalLayout() {             Rect r = new Rect();             activityRootView.getWindowVisibleDisplayFrame(r);              int heightDiff = activityRootView.getRootView()                     .getHeight() - (r.bottom - r.top);             if (lastDiff == heightDiff)                 return;             lastDiff = heightDiff;             Log.i("aerfin","arefin "+lastDiff);             if (heightDiff > 100) { // if more than 100 pixels, its                                     // probably a keyboard...                 flag2 = 0;             } else {                 if (flag == false)                     flag2 = 1;             }         }     }); 

3. Handling user interaction

 @Override  public void onUserInteraction() {      super.onUserInteraction();      flag = true;  } 

4. Finally onPause and onResume

@Override protected void onPause() {     super.onPause();     flag = true; }  @Override protected void onResume() {     flag = false;      switch (flag2) {     case 0:         getWindow().setSoftInputMode(                 WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);         break;     case 1:         getWindow().setSoftInputMode(                 WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);          break;     default:         break;     }      super.onResume(); } 

Explanation:

Here I used two flags (flag2 and flag). flag2 preserves the keyboardstate and flag preserves whether the application goes to background or is there any user interaction. flag is used because when application goes to background then at first it hides the keyboard. Other things can be easily understood from the code above.

Test:

tested in s2(ics), desire s (ics), galaxy y (2.3.6)

Final comment:

I wrote the code quickly so might be missed some other optimization. Also there might be chance of exceptional cases. If the screen changes for some reasons other than keyboard then it might not be able to detect keyboard state.

like image 100
5 revs, 3 users 81% Avatar answered Sep 23 '22 03:09

5 revs, 3 users 81%


You should use a flag (boolean kbShowing) to keep the current keyboard status, such as set kbShowing = true when keyboard show, otherwise set kbShowing = false.

onCreate

    showKB(); // if keyboard is not showed automatically.  

onRestart

    if(kbShowing)         showKb(); // if keyboard is not showed automatically.      else          hideKb(); // if keyboard is showed automatically. 

If you don't know how to detect when keyboard show or hide, chck Stefan's answer on this topic How to capture the "virtual keyboard show/hide" event in Android?

like image 20
Wayne Avatar answered Sep 21 '22 03:09

Wayne