android.view.View.systemUiVisibility deprecated. What is the replacement?
AndroidKotlinAndroid Problem Overview
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.
Android Solutions
Solution 1 - Android
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
Solution 2 - Android
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/
Solution 3 - Android
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())
}
Solution 4 - Android
As of version 1.5.0-alpha02
, androidx.core
has WindowCompat.setDecorFitsSystemWindows()
To enable edge-to-edge:
WindowCompat.setDecorFitsSystemWindows(window, false)
Solution 5 - Android
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());
}
}
}
Solution 6 - Android
WindowCompat.setDecorFitsSystemWindows(window, false)
Watch this tutorial from official Android Developers channel.
Solution 7 - Android
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.
Solution 8 - Android
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.
Solution 9 - Android
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
Solution 10 - Android
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
Solution 11 - Android
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);
}
Solution 12 - Android
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
Solution 13 - Android
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
Solution 14 - Android
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){
}
Solution 15 - Android
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.
Solution 16 - Android
use this : window.setDecorFitsSystemWindows(false)
Make sure that you have android build gradle setup that has minsdk of 30