Search code examples
androidandroid-fragmentsandroid-navigation-bar

Cannot hide navigation bar from inside a fragment


I currently have a ViewPager with a FragmentStatePagerAdapter. The problem here is that a navigation bar appears whenever I click a button, so I started manually hiding it with the following code:

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);

This code snippet works fine inside an activity, but doesn't do anything in a fragment. For all similar stackoverflow answers, they recommend to add getActivty() like below:

getActivity().getWindow().getDecorView()………..

BUT FOR SOME REASON IT IS STILL NOT HIDING THE NAVIGATION BAR


Solution

  • After failing for a couple of days to solve this problem, I finally decided to go back and read the android documentation. So I solved the problem by enabling sticky immersive mode whenever activity's window focus is changed, like below:

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
    // I removed the below condition check because I still want to hide System UI even if activity
    // loses focus. Such cases include spinner dropdown list is open, dialog box is displayed, etc.
    // if(hasFocus)
        hideSystemUI();
    }
    
    private void hideSystemUI() {
        // Enables sticky immersive mode.
        // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE_STICKY.
        // Or for "regular immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE
        View decorView = getWindow().getDecorView();
        decorView.setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                        // Set the content to appear under the system bars so that the
                        // content doesn't resize when the system bars hide and show.
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        // Hide the nav bar and status bar
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN);
    }
    
    // Shows the system bars by removing all the flags
    // except for the ones that make the content appear under the system bars.
    private void showSystemUI() {
        View decorView = getWindow().getDecorView();
        decorView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }
    

    Note: The reason why I enabled sticky immersive mode instead of the regular immersive mode is that with regular immersive mode, non-translucent navigation bar will be permanently displayed when user gestures from bottom to top. But with sticky immersive mode, a translucent navigation bar will be temporarily displayed.

    Update: I forgot to link this to the question. Since the onWindowFocusChanged(boolean hasFocus) will be triggered even if the focus changes are caused by a fragment task, there is no need to hide the System UI from inside the fragment.