0

Since Android 11 the correct way of displaying a fully immersive fragment is by hiding and showing StatusBar and NavigationBars via the following code which fully supports all devices with a camera notch, at any API level. Note the WindowCompat version replaces the framework version, so you don’t need to check for a particular API level as you did when using the framework version.

Hide

WindowCompat.SetDecorFitsSystemWindows(Activity.Window, false);   
WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.GetInsetsController(Activity.Window, Activity.Window.DecorView);
windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());

Show

WindowCompat.SetDecorFitsSystemWindows(Activity.Window, true); 
WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.GetInsetsController(Activity.Window, Activity.Window.DecorView);
windowInsetsControllerCompat.Show(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());

This eliminated the overly complex, very poorly documented and potentially error-prone code like below, which was used prior to Android 11.

Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.Fullscreen           |
                                                                       SystemUiFlags.HideNavigation       |
                                                                       SystemUiFlags.Immersive            |
                                                                       SystemUiFlags.ImmersiveSticky      |
                                                                       SystemUiFlags.LayoutHideNavigation |
                                                                       SystemUiFlags.LayoutStable         |
                                                                       SystemUiFlags.LowProfile);

I was attempting to provide a choice of either displaying all fragments fully immersive or allowing some fragments to display as “letterboxed” i.e. not allowing the window to render into the DisplayCutout area. So my existing preference choice Devices with Notches/Cutouts allow full screen display would have to change to support multiple choice.

The problem I hit was that code I had used (like the WindowCompat code above since Android 11) was failing to display the fragment fullscreen when first launched. When it opened for the first time the window would attempt to go full screen, but only the NavigationBar would be removed. The StatusBar area was left as a black rectangle. You could see the animation of the time on the left and the icons on the right side of the StatusBar disappearing, (statusBar contents removed) but the window didn’t render into the StatusBar area. Immediately when rotated, the fragment became full screen and when rotated back to Portrait it corrected itself and was full screen again.

So in frustration, I went hunting on StackOverFlow looking for a solution but everything I found suggested that my ImmersiveFragment class was coded correctly. Then because this was my first attempt at using Material 3, I then started to suspect Material3, so I went backwards to my NavigationGraph6 project (Material2) and after much testing, I was able to reproduce the same problem, which eliminated Material3.

More searching on StackOverflow and I came across a Kotlin post that was the same as all the others, except that it had the following line – equivalent to this C# line.

Activity.Window.AddFlags(WindowManagerFlags.LayoutNoLimits)

So I added that line before the WindowCompat.SetDecorFitsSystemWindows(Activity.Window, false) in the HideSystemUi() and then cleared the flags before the WindowCompat.SetDecorFitsSystemWindows(Activity.Window, true) line in the ShowSystemUi with

Activity.Window.ClearFlags(WindowManagerFlags.LayoutNoLimits) 

and immediately it worked.

So my question is why is this required and has anyone come across the same problem with immersive fragments?

Definition of LayoutNoLimits – Allow window to extend outside of the screen ???.

Does anyone have a clue what this definition actually means?

To test the code (comment out the new lines in ImmersiveFragment.cs). You can find the project NavigationGraph7 at https://github.com/gmck/NavigationGraph7. The immersiveFragment is the RaceResultsFragment (inherits from ImmersiveFragment) accessed by the BottomNavigationBar on the SlideShowFragment.

user2153142
  • 431
  • 1
  • 4
  • 7

1 Answers1

0

I referred to the official doc both Android and Microsoft too. As you said that: "Allow window to extend outside of the screen". There are few official definitions of it...

You can check Can I set FLAG_LAYOUT_NO_LIMITS only for status bar?, it talks about usage of LayoutNoLimit. Wish it could be helpful to you.

Jianwei Sun - MSFT
  • 2,289
  • 1
  • 3
  • 7
  • Each definition says the same thing. "Extend outside the screen". Outside the screen is the device's bezel, so obviously, the Google docs mean something else. Your link points to a question about transparent StatusBars - not really relevant as the sample app already has a preference setting to allow a transparent status or not, on non-immersive screens using Window.SetStatusBarColor. I'm just frustrated because I now can't find the original thread. I'd like to ask the guy if he hit the same problem as I did. The point is you shouldn't need to use it. – user2153142 Nov 22 '22 at 21:46