Search code examples
androidxamlmaui.net-mauimaui-community-toolkit

Unable to change the StatusBar when at the splashscreen for light and dark themes


I am trying to change the color/style of the StatusBar based on the device being set to light or dark theme, but not having much luck.

The following XAML works once the app has loaded, but does not work on the splash screen:

<ContentPage.Behaviors>
    <toolkit:StatusBarBehavior StatusBarColor="#F8F9FB" StatusBarStyle="DarkContent"  />
</ContentPage.Behaviors>

Look of StatusBar during splashscreen: enter image description here

Look of StatusBar once app has loaded: enter image description here

As you can see, the XAML above does not seem to affect the StatusBar during the splashscreen, as it is still showing it's default purple color with white text. Any idea how to change the StatusBar while the app is showing the splashscreen?

The end goal is the set the statusbar color and icon colors accordingly based on the device being set to light or dark theme. For example, if the device is set to use the dark theme, the statusbar while showing the splashscreen and the app shell should be a dark background with light text/icons. When the device is set to use the light theme, the statusbar while showing the splashscreen and the app shell should be a light background with dark text/icons.

I have checked many many existing questions about this, but they all seem to be obsolete, as I am using API 33.


Solution

  • In the beginning, the status bar color on Android is set by the MainActivity which you are seeing in your first screenshot of the splash screen. The StatusBarBehavior only kicks in once the hosted MAUI app is loaded in the MainActivity.

    UPDATE

    In .NET MAUI, you can replace the Maui.SplashTheme theme which is set in the MainActivity class with your own Theme, e.g. MyAppTheme:

    [Activity(Theme = "@style/MyAppTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
    public class MainActivity : MauiAppCompatActivity
    {
        //...
    }
    

    You can create your own themes in order to set the color of the splash screen incl. the status bar, you will need to create one for Dark and one for Light mode separately.

    Light Mode

    In your MAUI project, navigate to the Platforms/Android/Resources/ folder and, if not present yet, add a values subfolder. In this folder, create two files (or edit the existing ones):

    • colors.xml
    • styles.xml

    Attention: The styles.xml actually probably already exists and is simply hidden. If so, right-click on the values folder and select Add -> Existing Item and then select the styles.xml file in that location.

    Then, in your colors.xml define some colors, e.g.:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="colorPrimary">#FF00FF</color>
        <color name="colorPrimaryDark">#019FF5</color>
        <color name="colorAccent">#019FF5</color>
    </resources>
    

    Next, create your own Theme in the styles.xml, inherit from Maui.SplashTheme and set your color for the android:windowSplashScreenBackground item:

    <?xml version="1.0" encoding="utf-8" ?>
    <resources>
      <style name="MyAppTheme" parent="Maui.SplashTheme">
        <item name="android:windowSplashScreenBackground">@color/colorPrimary</item>
        <item name="android:windowLightStatusBar">true</item>
      </style>
    </resources>
    

    This will set up your splash screen color when the user is using the Light theme of Android.

    Dark Mode

    For Dark theme, you need to do essentially the same as for the Light theme, with a small difference.

    In your MAUI project, add the following subfolder: Platforms/Android/Resources/values-night (note the -night suffix). In this folder, again create the two files:

    • colors.xml
    • styles.xml

    In your colors.xml define some colors, e.g.:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="colorPrimary">#00FF00</color>
        <color name="colorPrimaryDark">#019FF5</color>
        <color name="colorAccent">#019FF5</color>
    </resources>
    

    Again, create your own Theme in the styles.xml, inherit from Maui.SplashTheme and set your color for the android:windowSplashScreenBackground item:

    <?xml version="1.0" encoding="utf-8" ?>
    <resources>
      <style name="MyAppTheme" parent="Maui.SplashTheme">
        <item name="android:windowSplashScreenBackground">@color/colorPrimary</item>
        <item name="android:windowLightStatusBar">false</item>
      </style>
    </resources>
    

    This will set up your splash screen color when the user is using the Dark theme of Android.

    Conclusion on Themes

    Since Maui.SplashTheme inherits from Theme.MaterialComponents.DayNight you can manipulate any kind of property for the display of native Android views and windows, e.g. the status bar and the action bar. This simply requires that a values and a values-night folder exist under Platforms/Android/Resources/ each containing a colors.xml and a styles.xml file.

    You can find the definition of the Maui.SplashTheme theme here: https://github.com/dotnet/maui/blob/main/src/Core/src/Platform/Android/Resources/values/styles.xml

    More on Android themes:

    Manipulate StatusBarColor at runtime

    After the MainActivity is loaded and your MAUI app is hosted, you can still manipulate the StatusBarColor by calling Window.SetStatusBarColor() anytime, for example like this (note that you can do this at any other place and use inversion of control to set the color from within your shared context):

    protected override void OnCreate(Bundle savedInstanceState) 
    { 
        base.OnCreate(savedInstanceState);
    
        //make sure only supported APIs use it
        if (Build.VERSION.SdkInt >= BuildVersionCodes.R)
        {
            if(AppInfo.RequestedTheme == AppTheme.Light)
            {
                Window.InsetsController?.SetSystemBarsAppearance((int)WindowInsetsControllerAppearance.LightStatusBars, (int)WindowInsetsControllerAppearance.LightStatusBars);
                //set color
                Window.SetStatusBarColor(Color.White);
            }
            else
            {
                Window.InsetsController?.SetSystemBarsAppearance(0, (int)WindowInsetsControllerAppearance.LightStatusBars);
    
                Window.SetStatusBarColor(Color.Black);
            }
        }
    }
    

    That's how I am using it in one of my current projects. I was wondering how to change the status bar during the Splash screen as well and figured out that you need to change the Maui.SplashTheme for that.

    Respond to theme changes

    If you need to change the theme based on the system theme during runtime and respond to changes, see the following:

    https://learn.microsoft.com/en-us/dotnet/maui/user-interface/system-theme-changes#react-to-theme-changes

    Note: You will need to use inversion of control or conditional compilation for this, if you want to explicitly set the status bar color during runtime from within your shared code. You can use any IoC container for this or follow James Montemagno's YT video: https://youtu.be/JCgxK0pWjNg

    If you are interested in letting the user choose the theme instead, checkout my blog article about Dark and Light themes with .NET MAUI:

    https://ewerspej.hashnode.dev/implement-dark-mode-in-net-maui