Sticky immersive mode disabled after soft keyboard shown Sticky immersive mode disabled after soft keyboard shown android android

Sticky immersive mode disabled after soft keyboard shown


Taken from this sample app by Google, you need to append this to the end of your activity, before the last end bracket:

@Overridepublic void onWindowFocusChanged(boolean hasFocus) {    super.onWindowFocusChanged(hasFocus);    // When the window loses focus (e.g. the action overflow is shown),    // cancel any pending hide action. When the window gains focus,    // hide the system UI.    if (hasFocus) {        delayedHide(300);    } else {        mHideHandler.removeMessages(0);    }}private void hideSystemUI() {    getWindow().getDecorView().setSystemUiVisibility(        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |         View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |         View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |         View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |         View.SYSTEM_UI_FLAG_FULLSCREEN |         View.SYSTEM_UI_FLAG_LOW_PROFILE |         View.SYSTEM_UI_FLAG_IMMERSIVE    );}private void showSystemUI() {    getWindow().getDecorView().setSystemUiVisibility(        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |         View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |         View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN    );}private final Handler mHideHandler = new Handler() {    @Override    public void handleMessage(Message msg) {        hideSystemUI();    }};private void delayedHide(int delayMillis) {    mHideHandler.removeMessages(0);    mHideHandler.sendEmptyMessageDelayed(0, delayMillis);}

And you should be good. :)


I put this code at onCreate() observer the layout changes

getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {    @Override    public void onGlobalLayout() {        Rect rect = new Rect();        getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);        int screenHeight = getWindow().getDecorView().getRootView().getHeight();        int keyboardHeight = screenHeight - rect.bottom;        if (keyboardHeight > screenHeight * 0.15) {             setToImmersiveMode();        }    }});private void setToImmersiveMode() {        // set to immersive        getWindow().getDecorView().setSystemUiVisibility(                View.SYSTEM_UI_FLAG_LAYOUT_STABLE                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_FULLSCREEN                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);    }


I suggest extending AppCompatActivity into a new class (ImmersiveAppCompatActivity). By doing this, any activity that you create using this class will have built in handling of immersive mode.

If you try and set immersive mode too quickly after the soft keyboard has appeared, it will not hide.

Also note that the handler has been improved by switching to a static handler - this will prevent leaks if the user leaves the activity before the GUI is hidden.

public abstract class ImmersiveAppCompatActivity extends AppCompatActivity {    private HideHandler mHideHandler;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // create a handler to set immersive mode on a delay        mHideHandler = new HideHandler(this);    }    @Override    protected void onResume() {        super.onResume();        setToImmersiveMode();    }    @Override    public void onWindowFocusChanged(boolean hasFocus) {        super.onWindowFocusChanged(hasFocus);        if(hasFocus) {            mHideHandler.removeMessages(0);            mHideHandler.sendEmptyMessageDelayed(0, 300);        }        else mHideHandler.removeMessages(0);    }    private void setToImmersiveMode() {        // set to immersive        getWindow().getDecorView().setSystemUiVisibility(                View.SYSTEM_UI_FLAG_LAYOUT_STABLE                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_FULLSCREEN                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);    }    private static class HideHandler extends Handler {        private final WeakReference<ImmersiveAppCompatActivity> mActivity;        HideHandler(ImmersiveAppCompatActivity activity) {            mActivity = new WeakReference<>(activity);        }        @Override        public void handleMessage(Message msg) {            ImmersiveAppCompatActivity activity = mActivity.get();            if(activity != null) activity.setToImmersiveMode();        }    }}

Here's the Kotlin version:

abstract class ImmersiveAppCompatActivity : AppCompatActivity() {    override fun onResume() {        super.onResume()        setToImmersiveMode()    }    override fun onWindowFocusChanged(hasFocus: Boolean) {        super.onWindowFocusChanged(hasFocus)        val runnable = Runnable { setToImmersiveMode() }        val handler = Handler(Looper.getMainLooper())        handler.postDelayed(runnable, 300)    }    private fun setToImmersiveMode() {        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                or View.SYSTEM_UI_FLAG_FULLSCREEN                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)    }}

Now, create your activity using this class:

public class SettingsActivity extends ImmersiveAppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();    }}

I've tested this in Android 5.1 and 7.0 to work in a full screen app that has no action bar.

Additionally, if you using the keyboard in an EditText be aware of the imeOptions. In landscape mode you can get strange full screen editing behavior. This can be disabled by setting imeOptions flags which are contained in the class EditorInfo:

<EditText    android:layout_width="@dimen/pin_width"    android:layout_height="wrap_content"    android:inputType="numberPassword"    android:imeOptions="flagNoExtractUi"    android:ems="10"    android:id="@+id/editTextPIN"    android:textSize="@dimen/pin_large_text_size"/>

https://developer.android.com/reference/android/view/inputmethod/EditorInfo.html