Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fullscreen #5478

Open
Realgigabyte opened this issue Mar 21, 2022 · 35 comments
Open

Fullscreen #5478

Realgigabyte opened this issue Mar 21, 2022 · 35 comments
Labels
area-controls-window Window legacy-area-desktop Windows / WinUI / Project Reunion & Mac Catalyst / macOS specifics (Menus & other Controls)) proposal/open t/desktop The issue relates to desktop scenarios (MacOS/MacCatalyst/Windows/WinUI/WinAppSDK) t/enhancement ☀️ New feature or request
Milestone

Comments

@Realgigabyte
Copy link

Description

I would like the option to show the app in full screen on Windows (without any border or title) and Android ("immersive" mode).

Public API Changes

'''csharp
var contentpage = new ContentPage;
Contenpage.Fullscreen= true; //this will make the window borderless and fullscreen

//this is just an example, any other way would be great

Intended Use-Case

My application need is a presentation display and require fullscreen.

@robertodalmonte
Copy link

I'd really like to have that functionality too.

@jfversluis jfversluis added this to the Future milestone Mar 24, 2022
@ghost
Copy link

ghost commented Mar 24, 2022

We've moved this issue to the Future milestone. This means that it is not going to be worked on for the coming release. We will reassess the issue following the current release and consider this item at that time.

@Eilon Eilon added the legacy-area-desktop Windows / WinUI / Project Reunion & Mac Catalyst / macOS specifics (Menus & other Controls)) label Mar 25, 2022
@arthurLNF
Copy link

Has this feature been reconsidered or already being implemented?

@SandroCODTEC
Copy link

This is a sorely needed feature for me. Currently I work with a reading screen that when I go up the page I need to hide the status bar and the navigation buttons.

@ewerspej
Copy link

Generally, it is possible for Android and iOS to have a "fullscreen" or "immersive" experience. However, it is very tedious to implement it separately for each platform. It would be convenient to have this functionality either directly in MAUI or in the Community Toolkit.

@LahkLeKey
Copy link

net7.0rc-1

Windows

MauiProgram.cs
#if WINDOWS
            // using Microsoft.Maui.LifecycleEvents;
            // #if WINDOWS
            //            using Microsoft.UI;
            //            using Microsoft.UI.Windowing;
            //            using Windows.Graphics;
            // #endif

            builder.ConfigureLifecycleEvents(events =>
                {
                    events.AddWindows(windowsLifecycleBuilder =>
                        {
                            windowsLifecycleBuilder.OnWindowCreated(window =>
                                {
                                    window.ExtendsContentIntoTitleBar = false;
                                    var handle = WinRT.Interop.WindowNative.GetWindowHandle(window);
                                    var id = Win32Interop.GetWindowIdFromWindow(handle);
                                    var appWindow = AppWindow.GetFromWindowId(id);
                                    switch (appWindow.Presenter)
                                    {
                                        case OverlappedPresenter overlappedPresenter:
                                            overlappedPresenter.SetBorderAndTitleBar(false, false);
                                            overlappedPresenter.Maximize();
                                            break;
                                    }
                                });
                        });
                });
#endif

Android

Platforms/Android/MainActivity.cs
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : MauiAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Platform.Init(this, savedInstanceState);

        this.Window?.AddFlags(WindowManagerFlags.Fullscreen);
    }
}

(Edit MainPage.xml if you are still not full screen in windows)

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Adverse_Player"
             x:Class="YourApp.MainPage"
             Title=""
             NavigationPage.HasNavigationBar="False">

    <BlazorWebView HostPage="wwwroot/index.html">
        <BlazorWebView.RootComponents>
            <RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
        </BlazorWebView.RootComponents>
    </BlazorWebView>

</ContentPage>

@Taiizor
Copy link

Taiizor commented Oct 26, 2022

net7.0rc-1

Windows

MauiProgram.cs
#if WINDOWS
            // using Microsoft.Maui.LifecycleEvents;
            // #if WINDOWS
            //            using Microsoft.UI;
            //            using Microsoft.UI.Windowing;
            //            using Windows.Graphics;
            // #endif

            builder.ConfigureLifecycleEvents(events =>
                {
                    events.AddWindows(windowsLifecycleBuilder =>
                        {
                            windowsLifecycleBuilder.OnWindowCreated(window =>
                                {
                                    window.ExtendsContentIntoTitleBar = false;
                                    var handle = WinRT.Interop.WindowNative.GetWindowHandle(window);
                                    var id = Win32Interop.GetWindowIdFromWindow(handle);
                                    var appWindow = AppWindow.GetFromWindowId(id);
                                    switch (appWindow.Presenter)
                                    {
                                        case OverlappedPresenter overlappedPresenter:
                                            overlappedPresenter.SetBorderAndTitleBar(false, false);
                                            overlappedPresenter.Maximize();
                                            break;
                                    }
                                });
                        });
                });
#endif

Android

Platforms/Android/MainActivity.cs
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : MauiAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Platform.Init(this, savedInstanceState);

        this.Window?.AddFlags(WindowManagerFlags.Fullscreen);
    }
}

(Edit MainPage.xml if you are still not full screen in windows)

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Adverse_Player"
             x:Class="YourApp.MainPage"
             Title=""
             NavigationPage.HasNavigationBar="False">

    <BlazorWebView HostPage="wwwroot/index.html">
        <BlazorWebView.RootComponents>
            <RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
        </BlazorWebView.RootComponents>
    </BlazorWebView>

</ContentPage>

What about for iOS and MacCatalyst (:

@samhouts samhouts added the t/enhancement ☀️ New feature or request label Dec 12, 2022
@jasonmillernc99
Copy link

I am using the following code below. The application starts in full screen; however, when I enter a value into an entry the black box for the navigation buttons appears at the bottom of the screen. I have disabled the soft keyboard and navigation buttons which do not show. I am not able to make the black box background go away. Any help would be appreciated.

if (this.Window != null)
{
this.Window.AddFlags(WindowManagerFlags.Fullscreen);
this.Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
if (Build.VERSION.SdkInt >= BuildVersionCodes.R)
{
#pragma warning disable CA1416
try
{
IWindowInsetsController wicController = Window.InsetsController;
if (wicController != null)
{
wicController.Hide(WindowInsets.Type.Ime());
wicController.Hide(WindowInsets.Type.NavigationBars());
wicController.Hide(WindowInsets.Type.SystemBars());
wicController.Hide(WindowInsets.Type.StatusBars());
}
}
catch { }
#pragma warning restore CA1416
}
else
{
#pragma warning disable CS0618
try
{
Android.Views.View decorView = Window.DecorView;
int uiOptions = (int)decorView.SystemUiVisibility;
uiOptions |= (int)SystemUiFlags.Fullscreen;
uiOptions |= (int)SystemUiFlags.HideNavigation;
uiOptions |= (int)SystemUiFlags.Immersive;
uiOptions |= (int)SystemUiFlags.ImmersiveSticky;
uiOptions |= (int)SystemUiFlags.LayoutHideNavigation;
uiOptions |= (int)SystemUiFlags.LayoutStable;
uiOptions |= (int)SystemUiFlags.LayoutFullscreen;
uiOptions |= (int)SystemUiFlags.LowProfile;
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;
}
catch { }
#pragma warning restore CS0618
}
}

screen without box
Screen with box

@LahkLeKey
Copy link

LahkLeKey commented Dec 22, 2022

I believe that is the taskbar not the navigation bar. You can either disable it in system settings or take a look at #8575 (comment)

https://android.stackexchange.com/questions/249098/how-to-disable-bottom-app-toolbar-on-samsung-tab-running-android-12

@dimplevador
Copy link

Anyone looking for a centralized way of achieving fullscreen without having to mess with the Platform specific files can use the code below. You can also use it to switch the fullscreen on and off based on some app logic. Our requirement was to set fullscreen mode according to user settings.

I haven't figured out yet how to do it programmatically for iOS and MacCatalyst. This code is for Android and Windows only. It took me a while to figure out the correct casting and code with lots of debugging... as the documentation for all this is practically non-existent with different versions of Dot Net having different syntax, adding to the confusion.

Let me know if you find any bug :)

Dotnet: 7

In App.xaml.cs file:

using Application = Microsoft.Maui.Controls.Application;
using Platform = Microsoft.Maui.ApplicationModel.Platform;

#if ANDROID
using View = AndroidX.Core.View;
#endif

#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using WinRT;
using Microsoft.Maui.Controls;
#endif

namespace MyApp;

public partial class App : Application
{
    private bool FullScreenMode { get; set; }
    
    public App()
    {
        FullScreenMode = false;
        
        InitializeComponent();

        MainPage = new MainPage();
    }
    
    protected override Window CreateWindow(IActivationState? activationState)
    {
        Window window = base.CreateWindow(activationState);
        
        window.Created += (s, e) =>
        {
            FullScreenMode = true; //NOTE: Change this to fetch the value true/false according to your app logic.
            SetFullScreen(s, e);
        };

        window.Resumed += (s, e) =>
        {
            //When resumed, the nav & status bar reappeared for android.
            //Fixing it by calling SetFullScreen again on resume,
            //If fullscreen had been set.
            //Not sure if it is needed for windows. Haven't tested yet.
            if (FullScreenMode)
            {
                SetFullScreen(s, e);    
            }
        };
        
        return window;
    }

    private void SetFullScreen(object? sender, EventArgs eventArgs)
    {
#if ANDROID
        SetFullScreenAndroid();
#endif
#if WINDOWS
        SetFullScreenWindows(sender, eventArgs);
#endif
    }
    
    private void SetFullScreenAndroid()
    {
#if ANDROID
        var activity = Platform.CurrentActivity;
        
        if (activity == null || activity.Window == null) return;
        
        View.WindowCompat.SetDecorFitsSystemWindows(activity.Window, !FullScreenMode);
        var windowInsetsControllerCompat = View.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
        var types = View.WindowInsetsCompat.Type.StatusBars() |
                    View.WindowInsetsCompat.Type.NavigationBars();
                
               
        if(FullScreenMode) 
        {
            windowInsetsControllerCompat.SystemBarsBehavior = View.WindowInsetsControllerCompat.BehaviorShowBarsBySwipe;
            windowInsetsControllerCompat.Hide(types);
        }
        else
        {
            windowInsetsControllerCompat.Show(types);
        }
#endif
    }
    
    private void SetFullScreenWindows(object? sender, EventArgs eventArgs)
    {
#if WINDOWS
        if(sender is not null)
        {
            var currentWindow = sender.As<Window>();
            var uiWindow = currentWindow.Handler.PlatformView.As<MauiWinUIWindow>();
            var handle = WinRT.Interop.WindowNative.GetWindowHandle(uiWindow);
            var id = Win32Interop.GetWindowIdFromWindow(handle);
            var appWindow = AppWindow.GetFromWindowId(id);
            switch (appWindow.Presenter)
            {
                case OverlappedPresenter overlappedPresenter:
                    //uiWindow.ExtendsContentIntoTitleBar = true;
                    if(FullScreenMode) {
                        overlappedPresenter.SetBorderAndTitleBar(false, false);
                        overlappedPresenter.Maximize();
                    }
                    else
                    {
                        overlappedPresenter.SetBorderAndTitleBar(true, true);
                        overlappedPresenter.Restore();
                    }
                    break;
            }                
        }
#endif
    }
}

@Realgigabyte
Copy link
Author

Realgigabyte commented Feb 12, 2023

Hi jasonmillernc99,
thanks a lot for the post. This works great.
Only thing in order to achieve real full screen in Windows without showing the titlebar:

//uiWindow.ExtendsContentIntoTitleBar = true;

needs to be changed to:

uiWindow.ExtendsContentIntoTitleBar = false;

@mouralabank
Copy link

Any updates? Fullscreen capability can be a useful feature for desktop apps both Mac and Windows, as it allows users to focus solely on the application without any distractions from other open windows or desktop icons. This can be particularly helpful for applications that require full attention, such as video editing, gaming, or graphic design.

@jfversluis
Copy link
Member

@mouralabank it is already possible today, see the above provided code snippets. I also wrote about it here: https://blog.verslu.is/maui/full-screen-disable-minimize-maximize-for-net-maui-windows-apps/

The API in .NET MAUI could definitely be easy, but seeing that there are good options available to do this today, I don't think this will be prioritized soon.

@mouralabank
Copy link

@mouralabank it is already possible today, see the above provided code snippets. I also wrote about it here: https://blog.verslu.is/maui/full-screen-disable-minimize-maximize-for-net-maui-windows-apps/

The API in .NET MAUI could definitely be easy, but seeing that there are good options available to do this today, I don't think this will be prioritized soon.

@jfversluis Thanks for the tip, very useful! I want to give you a suggestion, I believe that videos for MAUI Desktop can be very impactful to promote and expand the community and resources! I see a lot of potential in the MAUI desktop yet to be discovered and growing!!!

@ne0rrmatrix
Copy link

ne0rrmatrix commented Apr 4, 2023

I have started a discussion in the community toolkit to talk about adding full screen for both windows and android to the toolkit. I have tested my code and added it to a fork of toolkit and spent some time testing code. It still needs discussion and I am sure my code needs revision but I am waiting on someone to review the discussion and decide if SetFullScreen() and RestoreScreen() will make it into the toolkit. Here is a link to discussion if anyone wants to comment or like it I would appreciate feedback.

Link to discussion: https://github.com/CommunityToolkit/Maui/discussions/1123
Link to fork: https://github.com/ne0rrmatrix/Maui/tree/FullScreen

@Brionvega
Copy link

Brionvega commented May 19, 2023

@dimplevador , I've been experimenting with different methods to achieve a full immersive experience on Android devices, and I came across your workaround code. I wanted to thank you for sharing it. I tested the code on my Android 30 device, and it worked perfectly.

However, I encountered issues when I tried running it on my other testing device, which runs on Android 29. On the Android 29 device, the mobile status bar area is completely covered with a black strip, and the keyboard overlaps text input fields. This behavior is preventing me from achieving the desired immersive experience.

I would greatly appreciate any suggestions or workarounds that you or anyone else could offer to address this problem. I'm also open to exploring alternative approaches or libraries that can provide a consistent fullscreen experience across different Android versions.

Thank you in advance for any assistance or insights you can provide!

@dimplevador
Copy link

dimplevador commented May 20, 2023

@Brionvega Glad it helped :)

Regarding Keyboard overlapping text input fields, you have to set WindowSoftInputMode = SoftInput.AdjustResize in your MainActivity.cs ConfigurationChanges. That had worked for me.
Another solution for it is in App.xaml.cs constructor, you have to add this line:
Current?.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);

Try both. Whichever works :)

======

I don't have a device with Android 29 on hand but you can try the following code and see if it helps

    private void SetFullScreenAndroid()
    {
#if ANDROID
        var activity = Platform.CurrentActivity;
        
        if (activity == null || activity.Window == null) return;
        
        View.WindowCompat.SetDecorFitsSystemWindows(activity.Window, !FullScreenMode);
        var windowInsetsControllerCompat = View.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
        windowInsetsControllerCompat.SystemBarsBehavior = View.WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
        
        var types = View.WindowInsetsCompat.Type.StatusBars() |
                    View.WindowInsetsCompat.Type.NavigationBars();
                
               
        if(FullScreenMode) 
        {
            windowInsetsControllerCompat.Hide(types);
        }
        else
        {
            windowInsetsControllerCompat.Show(types);
        }
#endif
    }
    
    

@Brionvega
Copy link

@dimplevador Thank you so much for your response and for providing the additional guidance!
I appreciate you sharing the updated code snippet for setting fullscreen on Android. I will integrate the updated code snippet you shared for setting fullscreen on Android into my project and test it out. Thank you once again for your help and suggestions. I really appreciate your assistance in resolving this issue :)

@xx7Ahmed7xx
Copy link

@dimplevador I tried the global one (i.e
Current?.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>() .UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize); )
And this actually works! thanks so much!

@dimplevador
Copy link

@dimplevador I tried the global one (i.e Current?.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>() .UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize); ) And this actually works! thanks so much!

@xx7Ahmed7xx Glad it worked :)

@Irasil
Copy link

Irasil commented Sep 20, 2023

I need this for MacOS or rather a way how I can run a Maui app in the system tray of MacOS :)

@ne0rrmatrix
Copy link

ne0rrmatrix commented Sep 20, 2023

Here is a repo that has support for Page full screen. https://github.com/ne0rrmatrix/MauiPageFullScreen
Here is a link to Nuget package: https://www.nuget.org/packages/FullScreenStatus.Maui/

Supports Windows, IOS, and android. Can be used in shell, Navigation Page, and Tabbed Page.

Does not support Mac Catalyst. I have no idea how to do that. I can add hiding the bars but full screen on Mac still requires someone to make a lib and add it. I will be looking into doing that but I am having a hard time with visual studio on my mac mini. It is terribly difficult to work with. yes I know there are other solutions out there. Just have not had time to look into that yet.

@jonmdev
Copy link

jonmdev commented Oct 1, 2023

Basic full screen function can be had quite easily by adding the following for Windows and Android the Program.cs code:

#if WINDOWS
            builder.ConfigureLifecycleEvents(events =>
            {
                events.AddWindows(lifeCycleBuilder =>
                {
                    lifeCycleBuilder.OnWindowCreated(w =>
                    {
                        w.ExtendsContentIntoTitleBar = false;
                        IntPtr wHandle = WinRT.Interop.WindowNative.GetWindowHandle(w);
                        WindowId windowId = Win32Interop.GetWindowIdFromWindow(wHandle);
                        AppWindow mauiWindow = AppWindow.GetFromWindowId(windowId);
                        mauiWindow.SetPresenter(AppWindowPresenterKind.FullScreen);  // TO SET THE APP INTO FULL SCREEN
                    });
                });
            });

#endif
#if ANDROID
            builder.ConfigureLifecycleEvents(events => {
                events.AddAndroid(android => android.OnCreate((activity, bundle) => MakeFullScreen(activity)));
                events.AddAndroid(android => android.OnCreate((activity, bundle) => MakeStatusBarTranslucent(activity)));

                
                void MakeStatusBarTranslucent(Android.App.Activity activity) {

                    activity.Window.ClearFlags(Android.Views.WindowManagerFlags.TranslucentStatus);
                    activity.Window.SetStatusBarColor(Android.Graphics.Color.Transparent);
                }
                void MakeFullScreenApplication(Android.App.Application application) {
                    MakeFullScreen(application.GetActivity());
                }

                void MakeFullScreen(Android.App.Activity activity) {

                    activity.Window.DecorView.SystemUiVisibility = (Android.Views.StatusBarVisibility)(
                                Android.Views.SystemUiFlags.LayoutStable
                                | Android.Views.SystemUiFlags.LayoutHideNavigation
                                | Android.Views.SystemUiFlags.HideNavigation// hide nav bar
                                | Android.Views.SystemUiFlags.Immersive
                                | Android.Views.SystemUiFlags.ImmersiveSticky //so returns to immersive after pull down done
                        );
                }
            });
#endif

It would be good to add a simple third method to this for iOS but I cannot find one. I tried installing this package:

https://github.com/ne0rrmatrix/MauiPageFullScreen

But it does not work for iOS for me - nothing happens with its invocation, although it does work in Windows. I think that package is just using Shell and Navigation page functions which don't work unless your app is using a Shell or Navigation Page.

Does anyone know what the equivalent Builder code would be for iOS?

@jonmdev
Copy link

jonmdev commented Oct 1, 2023

I see it claimed that one can make iOS full screen by adding the following values to the info.plist file:

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

This is claimed here for Xamarin at least:
https://learn.microsoft.com/en-us/answers/questions/863694/full-screen-app-on-ios-xamarin-forms

But this also does not work for me. I am Hot Reloading to iPhone XR as Debug build as I don't have a Mac. I note that MAUI states we cannot use custom App Icons or Splash Screen Icons when using this process. Perhaps this is the issue?

Can anyone confirm if the above method lets you build full screen for iOS or alternatively, any other ideas? To be clear, "full Screen" means it renders from the top of the screen to the bottom completely just like a splash screen.

Currently no matter what I do in iOS I get a white status bar at the top and a white pull up bar at the bottom. I would like both gone or at least to be rendering my app under them rather than having them as white bars top and bottom.

Any ideas?

@jonmdev
Copy link

jonmdev commented Oct 1, 2023

Made a new issue here as this seems like a deep problem in MAUI for iOS with no solution on our end unless I am still missing something:

#17767

@ne0rrmatrix
Copy link

jonmdev setting that key to false with:

<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>

will work with my nuget package. If you can test setting to false it would be appreciated. I forgot to add that plist code to sample and info on package. That will be fixed soon. If your app can work with the key set to false my solution should work for you.

@jonmdev
Copy link

jonmdev commented Oct 1, 2023

Thanks @ne0rrmatrix ne0rrmatrix, that does at least accomplish one thing: The status bar at the top text becomes invisible.

However, the status bar area (safe zone) is still occupying space with a white bar behind it and the home bar at the bottom are still present and both are stilling windowing the app top and bottom preventing full screen mode in iOS.

I found your code to do this is:

#if IOS || MACCATALYST
#pragma warning disable CA1422 // Validate platform compatibility
        UIKit.UIApplication.SharedApplication.SetStatusBarHidden(shouldBeFullScreen, UIKit.UIStatusBarAnimation.Fade);
#pragma warning restore CA1422 // Validate platform compatibility
#endif

At least that is one step in the right direction.

Perhaps I also need a method to render into the safe zone? Maybe that is a separate issue? (ie. status bar is hidden but still being blocked from full screen by safe zone).

@ne0rrmatrix
Copy link

You can disable the safe area. Here is an example: https://learn.microsoft.com/en-us/dotnet/maui/ios/platform-specifics/page-safe-area-layout

@jonmdev
Copy link

jonmdev commented Oct 2, 2023

Thanks @ne0rrmatrix ! That was perfect. I did not understand that method. For posterity, links explaining the methods are here:

https://learn.microsoft.com/en-us/dotnet/maui/ios/platform-specifics/page-safe-area-layout
https://stackoverflow.com/questions/74724489/net-maui-ios-usesafearea-not-working-stacklayout-verticalstacklayout-and-grid
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/ios/page-home-indicator

So to summarize for iOS, to get full screen, I did the following:

  1. Create page extensions to set page to full screen (as must be done on per page basis in iOS) and run this function on each page needing full screen:
using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;

namespace MauiProject {
    public static class PageExtensions {
        public static void setPageToFullScreen(this Microsoft.Maui.Controls.Page page) {
            page.On<Microsoft.Maui.Controls.PlatformConfiguration.iOS>().SetUseSafeArea(false);
            page.On<Microsoft.Maui.Controls.PlatformConfiguration.iOS>().SetPrefersHomeIndicatorAutoHidden(true);
        }
    }
}
  1. In Info.plist add:
<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
  1. And in builder I took your method with the Pragmas to suppress the version warning exactly like this:
#if IOS
            builder.ConfigureLifecycleEvents(events => {
                
                events.AddiOS(iOs => {
                    iOs.OnActivated(activated => {
#pragma warning disable CA1422 // Validate platform compatibility
                        activated.SetStatusBarHidden(true, UIKit.UIStatusBarAnimation.None);
#pragma warning restore CA1422 // Validate platform compatibility
                        System.Diagnostics.Debug.WriteLine("IOS ACTIVATED");
                    });
                    
                });
            });
#endif
  1. Set any layout objects to layout.IgnoreSafeArea = true;

Then if one wants to lay out things manually based on safe zone in iOS one can use: On<iOS>().SafeAreaInsets(); to get the size.

Do you know of any way to get the safe zone size so easily in Android? Thanks again.

@ne0rrmatrix
Copy link

Hmm. My NuGet package does that but if you want to do it yourself you can copy the page extensions from either MS https://github.com/dotnet/maui/blob/main/src/Controls/src/Core/Platform/PageExtensions.cs or better copy mine and then you can get the current page:

static Page CurrentPage => GetCurrentPage(Application.Current?.MainPage ?? throw new InvalidOperationException($"{nameof(Application.Current.MainPage)} cannot be null."));

Just remove the PageExtensions.SetBarStatus(true) if your using MS one. Mine accounts for things like having a title and handles all the variable etc when needed. It is a rather tiresome complicated thing to get right. Out of the box this will not work in many situations for MS default page extension method. Using my extension and the code below it will work for android.

public void FullScreen()
{
    PageExtensions.SetBarStatus(true);
    var activity = Platform.CurrentActivity;

    if (activity == null || activity.Window == null)
    {
        return;
    }

    Views.WindowCompat.SetDecorFitsSystemWindows(activity.Window, false);
    var windowInsetsControllerCompat = Views.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
    var types = Views.WindowInsetsCompat.Type.StatusBars() |
                Views.WindowInsetsCompat.Type.NavigationBars();

    windowInsetsControllerCompat.SystemBarsBehavior = Views.WindowInsetsControllerCompat.BehaviorShowBarsBySwipe;
    windowInsetsControllerCompat.Hide(types);
}

That sets full screen after page has loaded. It is near instant but does have a small animation fading the taskbar.

@jonmdev
Copy link

jonmdev commented Oct 2, 2023

Thanks. just to be clear, I was asking about how to get the safe zone inset sizes. I am already able to build into the safe zone and full screen Android using the method posted here which interestingly runs a bit differently than your strategy but accomplishes the same as yours and on immediate app build:

#5478 (comment)

I am able to also get iOS insets with the following which is working:

#if IOS
                UIKit.UIWindow window = UIKit.UIApplication.SharedApplication.Delegate.GetWindow();
                var bottomPadding = window.SafeAreaInsets.Bottom;
                var topPadding = window.SafeAreaInsets.Top;
                Debug.WriteLine("PAD BOTTOM " + bottomPadding + " TOP " + topPadding);
#endif

For Android, this seems to work on higher levels of Android but if there is no inset (no notch to cause safe zone) will not return correctly so must be protected against to return zero if objects don't exist:

var activity = Platform.CurrentActivity;
var insets = activity.Window.DecorView.RootView.RootWindowInsets;
var displaycutout = insets.DisplayCutout;
var corrected = this.ToPlatform(this.Handler.MauiContext).Context.FromPixels(displaycutout.SafeInsetTop);
Debug.WriteLine("ANDROID INSETS TOP " + displaycutout.SafeInsetTop + " BOT " + displaycutout.SafeInsetBottom + " CORRECTED " + corrected);

Thanks again for your help. Happy to have it all working.

@ne0rrmatrix
Copy link

ne0rrmatrix commented Oct 24, 2023

An update for Android full screen to get rid of obsolete method call in dotnet 8.

Restore Screen

   var activity = Platform.CurrentActivity;

   if (activity == null || activity.Window == null)
   {
       return;
   }

   Views.WindowCompat.SetDecorFitsSystemWindows(activity.Window, true);
   var windowInsetsControllerCompat = Views.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
   var types = Views.WindowInsetsCompat.Type.StatusBars() |
               Views.WindowInsetsCompat.Type.NavigationBars();
   windowInsetsControllerCompat.Show(types);
   windowInsetsControllerCompat.SystemBarsBehavior = Views.WindowInsetsControllerCompat.BehaviorDefault;

Full Screen

  var activity = Platform.CurrentActivity;

  if (activity == null || activity.Window == null)
  {
      return;
  }

  Views.WindowCompat.SetDecorFitsSystemWindows(activity.Window, false);
  var windowInsetsControllerCompat = Views.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
  var types = Views.WindowInsetsCompat.Type.StatusBars() |
              Views.WindowInsetsCompat.Type.NavigationBars();

  windowInsetsControllerCompat.SystemBarsBehavior = Views.WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
  windowInsetsControllerCompat.Hide(types);

The key changes are

  • Views.WindowInsetsControllerCompat.BehaviorDefault
  • Views.WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe
  • Setting SetDecorFitsSystemWindows(activity.Window, true) for Restore
  • Setting SetDecorFitsSystemWindows(activity.Window, false) for Full Screen

@neonleo
Copy link

neonleo commented Nov 21, 2023

MAUI definitely far from production use, full screen is simple few line of code to make it works on Android or React Native, but .NET 8.0 MAUI still missing of it
And thanks ne0rrmatrix make a Nuget package to make it happen.

@fe56
Copy link

fe56 commented Dec 4, 2023

I encountered the same issue. A workaround on Android for me was using this OnCreate method:

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Platform.Init(this, savedInstanceState);
        IWindowInsetsController wicController = Window.InsetsController;
        Window.SetDecorFitsSystemWindows(false);
        Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
        if (wicController != null)
        {
            wicController.Hide(WindowInsets.Type.SystemBars());
        }
    }

@Yu-Core
Copy link

Yu-Core commented May 1, 2024

For me, the best way is on Android

        protected override void OnCreate(Bundle savedInstanceState)
        {
            Google.Android.Material.Internal.EdgeToEdgeUtils.ApplyEdgeToEdge(Window, true);
            if (OperatingSystem.IsAndroidVersionAtLeast((int)BuildVersionCodes.Q))
            {
                Window.StatusBarContrastEnforced = false;
                Window.NavigationBarContrastEnforced = false;
            }

            base.OnCreate(savedInstanceState);
        }

@Eilon Eilon added the t/desktop The issue relates to desktop scenarios (MacOS/MacCatalyst/Windows/WinUI/WinAppSDK) label May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-controls-window Window legacy-area-desktop Windows / WinUI / Project Reunion & Mac Catalyst / macOS specifics (Menus & other Controls)) proposal/open t/desktop The issue relates to desktop scenarios (MacOS/MacCatalyst/Windows/WinUI/WinAppSDK) t/enhancement ☀️ New feature or request
Projects
None yet
Development

No branches or pull requests