121

I have updated the project target API version to 30, and now I see that the systemUiVisibility property is deprecated.

The following kotlin code is the one I'm using which is actually equivalent to setSystemUiVisibility method in Java.

playerView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
            or View.SYSTEM_UI_FLAG_FULLSCREEN
            or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)

Please let me know if you have got any stable replacement for this deprecated code. The google's recommendation is to use WindowInsetsController, but I don't how to do that.

Doctiger
  • 2,318
  • 2
  • 15
  • 28
  • 3
    @Doctinger do you find the solution ? I am confused how to implement the solutions below to playerView in exoplayer like your code. could you please your implementation ? :) – sarah Nov 10 '20 at 06:28

21 Answers21

98

For compatibility, use WindowCompat and WindowInsetsControllerCompat. You'll need to upgrade your gradle dependency for androidx.core to at least 1.6.0-alpha03 so that there will be support for setSystemBarsBehavior on SDK < 30.

private fun hideSystemUI() {
    WindowCompat.setDecorFitsSystemWindows(window, false)
    WindowInsetsControllerCompat(window, mainContainer).let { controller ->
        controller.hide(WindowInsetsCompat.Type.systemBars())
        controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }
}

private fun showSystemUI() {
    WindowCompat.setDecorFitsSystemWindows(window, true)
    WindowInsetsControllerCompat(window, mainContainer).show(WindowInsetsCompat.Type.systemBars())
}

You can find out more information about WindowInsets by watching this YouTube video

For devices with notches at the top of the display, you can add the following to your v27 theme.xml file make the UI appear either side of the notch:

<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>

You can read more at this link: Display Cutout

James
  • 4,573
  • 29
  • 32
  • 1
    One extra thing i didn't consider in this answer is display cutouts / in-display cameras. In the app theme style, i added the following to display my content above the cutout (to the top of the screen): `shortEdges` – James Jul 01 '21 at 04:04
  • you can also hide `navigationBars` alongside with `systemBars`: `controllerCompat.hide(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.navigationBars());` – Moisoni Ioan Jul 10 '21 at 16:29
  • 2
    @MoisoniIoan `systemBars()` includes "All system bars. Includes statusBars(), captionBar() as well as navigationBars(), but not ime()." Please see documentation: https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat.Type#systemBars() – James Jul 13 '21 at 16:45
  • 1
    It requires `mainContainer`, maybe it is `getRootView()` of an Activity. – CoolMind Jul 27 '21 at 17:24
  • 8
    @CoolMind, `mainContainer` is `window.decorView` – Florent Roques Oct 16 '21 at 21:07
  • @James if you swipe from the top, it's being visible and not hiding automatically, do you have any solution? – Vivek Thummar Apr 28 '23 at 06:39
  • whats window as parameter? – Rohit gupta Apr 28 '23 at 09:56
  • @Rohitgupta it's the window. See https://developer.android.com/reference/android/view/Window. You can get the window from an `Activity`. – James May 02 '23 at 19:47
39

TL;DR snippet

Wrapping in if-else structure needed to avoid java.lang.NoSuchMethodError: No virtual method setDecorFitsSystemWindows exception on older SDK versions.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    window.setDecorFitsSystemWindows(false)
} else {
    window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
}

Links with full information about insets and fullscreen modes in Android 11

https://blog.stylingandroid.com/android11-windowinsets-part1/

https://www.youtube.com/watch?v=acC7SR1EXsI

Konstantin Kuznetsov
  • 1,188
  • 10
  • 13
26

I hope It helps you.

Previously, when implementing edge-to-edge navigation or immersive mode, one of the first steps to take was to use the systemUiVisibility flags in order to request the app to be laid out fullscreen, This new Android release deprecates this field and in order to layout the app fullscreen you have to use a new method on the Window class: setDecorFitsSystemWindows passing false as an argument like below.

window.setDecorFitsSystemWindows(false)

WindowInsetsController class which allows you to do things that previously were controlled via systemUiVisibility flags, like hiding or showing the status bar or navigation bar(hide and show methods, respectively)

For example, you can easily show and hide the keyboard as shown below:

// You have to wait for the view to be attached to the
// window (otherwise, windowInsetController will be null)
view.doOnLayout {
    view.windowInsetsController?.show(WindowInsets.Type.ime())
    // You can also access it from Window
    window.insetsController?.show(WindowInsets.Type.ime())
}
hobin
  • 359
  • 2
  • 11
  • 12
    `window.setDecorFitsSystemWindows()` requires API level R. How can I solve the compatibility issue on the older API level? – Shuang Wu Aug 04 '20 at 03:51
  • Declare the android:minSdkVersion property on the application's manifest and set the value to the API level of the platform version. – hobin Aug 05 '20 at 06:08
  • 1
    Does that mean the `setDecorFitsSystemWindows` can only be used on the devices with Android R (which has extremely small distribution) ? – Shuang Wu Aug 05 '20 at 07:13
  • 2
    It sets whether the decor view should fit root-level content views for WindowInsets. it seems that it will only work with API 30. If It can't work properly. Do a version check – hobin Aug 05 '20 at 08:57
  • 5
    So, setDecorFitsSystemWindows cannot be used to get a full screen for API < 30. Thank you for the clarification. – Hong Sep 01 '20 at 19:35
19

As of version 1.5.0-alpha02, androidx.core has WindowCompat.setDecorFitsSystemWindows()

To enable edge-to-edge:

WindowCompat.setDecorFitsSystemWindows(window, false)
Phil
  • 241
  • 2
  • 2
  • Hi Phil, do you know how we can implement view.windowInsetsController?.hide(WindowInsets.Type.navigationBars()) or window.insetsController?.hide(WindowInsets.Type.navigationBars()) in a backward compartble manner? – Geob Aug 21 '20 at 11:50
  • 3
    @Geob Google is working on WindowInsetsController support library. source- https://www.youtube.com/watch?v=acC7SR1EXsI – Sourav Bagchi Aug 24 '20 at 17:49
13

If somebody search for Java version.

For Activity:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    getWindow().setDecorFitsSystemWindows(false);

    if (getWindow().getInsetsController() != null) {
        getWindow().getInsetsController().hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
        getWindow().getInsetsController().setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
    }
} else {
    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}

for FragmentDialog and AlertDialog:

if (getDialog() != null && getDialog().getWindow() != null) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        getDialog().getWindow().setDecorFitsSystemWindows(false);
    } else {
        if (getActivity() != null) {
            getDialog().getWindow().getDecorView().setSystemUiVisibility(getActivity().getWindow().getDecorView().getSystemUiVisibility());
        }
    }
}
anatoli
  • 1,663
  • 1
  • 17
  • 43
  • 1
    Thanks for including a Java version, I'm still holding out on changing my 100,000 lines of game code to Kotlin, getting fairly expert at Java and it's issues was hard enough. – Androidcoder Apr 26 '21 at 16:33
7

For Java users (thanks to @James):

//hide system UI
Window window = activity.getWindow();
View decorView = activity.getWindow().getDecorView();

WindowCompat.setDecorFitsSystemWindows(window, false);
WindowInsetsControllerCompat controllerCompat = new WindowInsetsControllerCompat(window, decorView);
controllerCompat.hide(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.navigationBars());
controllerCompat.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);

(Edit) Use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE to only show sytemBars temporarily when when swiping, BEHAVIOR_SHOW_BARS_BY_SWIPE will show them permanently after swiping.

Source : https://developer.android.com/reference/android/view/WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

Drarox
  • 11
  • 3
Moisoni Ioan
  • 1,370
  • 1
  • 13
  • 24
  • systemBars() includes navigationBars(), so only need to set one parameter: controllerCompat.hide(WindowInsetsCompat.Type.systemBars()) – Jason Yeung Aug 07 '22 at 20:33
6
WindowCompat.setDecorFitsSystemWindows(window, false)

Watch this tutorial from official Android Developers channel.

Sourav Bagchi
  • 656
  • 7
  • 13
5

If you are using Jetpack Compose, use this method in setContent:

@Composable
fun HideSystemUi()
{
    val systemUiController = rememberSystemUiController()

    SideEffect {
        systemUiController.isSystemBarsVisible = false
    }
}

Do not forget to add this to your app's build.gradle file (adjust the version if necessary):

implementation "com.google.accompanist:accompanist-systemuicontroller:0.17.0"

The documentation can be found here, although you might want to have a look at the sources.

Corbie
  • 819
  • 9
  • 31
5

2022 Offical Solution with Kotlin Code:

val windowInsetsController =
            ViewCompat.getWindowInsetsController(window.decorView) ?: return
        // Configure the behavior of the hidden system bars
        windowInsetsController.systemBarsBehavior =
            WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        // Hide both the status bar and the navigation bar
        windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())

Source: https://developer.android.com/training/system-ui/immersive#kotlin

Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
  • 3
    Unfortunately this is not working for me but "WindowInsetsControllerCompat(window, window.decorView).hide(WindowInsetsCompat.Type.statusBars())" is working fine. what I might be doing wrong here? – kallis May 27 '22 at 08:39
  • @kallis Try with different OS version, check your parent activity is AppCompatActivity or not, add this to your activity into manifest android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" , as this is the official android solution, it must work! – Kishan Solanki May 27 '22 at 08:56
3

According to Chris Banes @ Android Developers official youtube channel use following code

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var view: View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        view = binding.root
        setContentView(view)
    }

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        if (hasFocus) hideSystemUI()
    }

    private fun hideSystemUI() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
             // Tell the window that we want to handle/fit any system windows
             WindowCompat.setDecorFitsSystemWindows(window, false)

             val controller = view.windowInsetsController

             // Hide the keyboard (IME)
             controller?.hide(WindowInsets.Type.ime())

             // Sticky Immersive is now ...
             controller?.systemBarsBehavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

             // When we want to hide the system bars
             controller?.hide(WindowInsets.Type.systemBars())

             /*val flag = WindowInsets.Type.statusBars()
             WindowInsets.Type.navigationBars()
             WindowInsets.Type.captionBar()
             window?.insetsController?.hide(flag)*/
        } else {
            //noinspection
            @Suppress("DEPRECATION")
            // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
            window.decorView.systemUiVisibility = (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.
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                // Hide the nav bar and status bar
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN)
        }
    }
}

Here is Sample Link User interface sample

Vidyesh Churi
  • 1,899
  • 1
  • 24
  • 33
2

Also you may want to have a translucent status bar and you can do it simply through setting a style to your app's theme as follows:

<style name="App.MyTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <item name="android:windowLightStatusBar">true</item>
</style>

A lint message can be displayed (depending on you curren min api level): android:windowLightStatusBar requires API level 23 (current min is 21), so you need to override this theme in v23 styles

Carlos Daniel
  • 2,459
  • 25
  • 30
2

Kotlin Solution: Inside of Activity onCreate method add this:

window.setFlags(
        WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
        WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
    )
1

Here is a straight forward solution that works for all android version and hides the status bar

 WindowInsetsControllerCompat(window,  window.decorView).hide(WindowInsetsCompat.Type.systemBars())

It works well on emulators but sometimes on a real device if the keyboard pops up the status bar is shown again. If you don't really need to hide/show the status bar programmatically then just add window full screen as an item to the theme you will use for that screen. For example you can create a style in theme.xml

 <style name="HideStatusBar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
    <!-- hides status bar-->
    <item name="android:windowFullscreen">true</item>
</style>

and in the AndroidManifest.xml you add a style to that activity section

 <activity
        android:name=".MainActivity"
        android:screenOrientation="portrait"
   <!-- The style-->
        android:theme="@style/NoactionBar"
        android:exported="true" />

This also works for all version

Loveth
  • 361
  • 3
  • 7
1

JAVA

 private void showSystemUI() {
            WindowCompat.setDecorFitsSystemWindows(getWindow(), true);
            new WindowInsetsControllerCompat(getWindow(), yourRootView).show(WindowInsetsCompat.Type.systemBars());
        }

        private void hideSystemUI() {
            WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
            WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(getWindow(), yourRootView);
            controller.hide(WindowInsetsCompat.Type.systemBars());
            controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
        }
Sujith S Manjavana
  • 1,417
  • 6
  • 33
  • 60
1

For anyone looking to do this in Xamarin Forms and C#, I have added this code in the MainActivity class in the MainActivity.cs file:

    private void SetWindowLayout()
    {
        if (Window != null) {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.R) {
                IWindowInsetsController wicController = Window.InsetsController;


                Window.SetDecorFitsSystemWindows(false);
                Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);

                if (wicController != null) {
                    wicController.Hide(WindowInsets.Type.Ime           ());
                    wicController.Hide(WindowInsets.Type.NavigationBars());
                }
            }
            else {
                #pragma warning disable CS0618

                Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);

                Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.Fullscreen           |
                                                                       SystemUiFlags.HideNavigation       |
                                                                       SystemUiFlags.Immersive            |
                                                                       SystemUiFlags.ImmersiveSticky      |
                                                                       SystemUiFlags.LayoutHideNavigation |
                                                                       SystemUiFlags.LayoutStable         |
                                                                       SystemUiFlags.LowProfile);
                #pragma warning restore CS0618
            }
        }
    }

Then, in the OnCreate overridden method make a call to SetWindowLayout()

Then, override the OnWindowFocusChanged() method:

    public override void OnWindowFocusChanged(
        Boolean bHasFocus)
    {
        base.OnWindowFocusChanged(bHasFocus);

        if (bHasFocus)
            SetWindowLayout();
    }

I hope this helps everyone in Visual Studio.

Loz.

LozCool
  • 69
  • 3
1

Java version:

playerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE 
                | View.SYSTEM_UI_FLAG_FULLSCREEN 
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

Document recommendation (respectively):

  1. Low profile mode is deprecated. Hide the system bars instead

  2. Use WindowInsetsController#hide(int) with Type#statusBars()

  3. Use WindowInsets#getInsetsIgnoringVisibility(int)

  4. Use WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

  5. Use Window#setDecorFitsSystemWindows(boolean) with false.

  6. Use WindowInsetsController#hide(int) with Type#navigationBars()

So, the final code is:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        getWindow().setDecorFitsSystemWindows(false);

        playerView.getWindowInsetsController()
                .hide(WindowInsets.Type.systemBars()
                        | WindowInsets.Type.statusBars()
                        | WindowInsets.Type.navigationBars());

        playerView.getWindowInsetsController()
                .setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);

        playerView.getRootWindowInsets()
                        .getInsetsIgnoringVisibility(WindowInsets.Type.statusBars()
                                | WindowInsets.Type.navigationBars());

    }else {
        playerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
                | View.SYSTEM_UI_FLAG_FULLSCREEN 
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
    }
Amit
  • 53
  • 4
0

In the Styles file add two items:

<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>

And in activity file before setContentView(R.layout.activity_main) this following lines :

try {
   actionBar!!.hide();
} catch (e:Exception){
        
}
Elikill58
  • 4,050
  • 24
  • 23
  • 45
fazal ur Rehman
  • 330
  • 2
  • 5
0

For Android 11+ devices, and with the method hide(WindowInsets.Type.systemBars(), I get a problem when a popup is dynamically displayed. The navigation bar becomes visible and the background window is reduced. When the popup is closed, the navigation bar becomes hidden again and the background window is maximized.

With the method

setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)

previously used, there was no problem.

sweak
  • 1,369
  • 2
  • 6
  • 21
0

Kotlin - Fragment - Sep/2022 If anyone is interested for manage from Fregement Kotlin code!

private fun fullScreenOff() {
requireActivity().window.decorView.systemUiVisibility = (View.VISIBLE)}

private fun fullScreenOn() {
requireActivity().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)
}
Doctiger
  • 2,318
  • 2
  • 15
  • 28
sandip
  • 394
  • 1
  • 4
  • 11
-1
<style name="Theme.MobileCredentialsAndroidSample" 
       parent="Theme.MaterialComponents.Light.NoActionBar">
   <item name="android:windowFullscreen">true</item>
   ...
ItSNeverLate
  • 533
  • 7
  • 8
  • 3
    This answer was reviewed in the [Low Quality Queue](https://stackoverflow.com/help/review-low-quality). Here are some guidelines for [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). Code only answers are **not considered good answers**, and are likely to be downvoted and/or deleted because they are **less useful** to a community of learners. It's only obvious to you. Explain what it does, and how it's different / **better** than existing answers. [From Review](https://stackoverflow.com/review/low-quality-posts/32577452) – Trenton McKinney Aug 26 '22 at 23:30
-3

use this : window.setDecorFitsSystemWindows(false)

Make sure that you have android build gradle setup that has minsdk of 30