5

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.

oshirowanen
  • 15,297
  • 82
  • 198
  • 350

2 Answers2

5

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

Julian
  • 5,290
  • 1
  • 17
  • 40
  • Unable to try option 3 as my project does not have a styles.xml in platforms/Android/Resources/values. Tried option 1 and it works, but how would I chance the font/icon color to something darker? – oshirowanen Oct 18 '22 at 18:03
  • Target API is 33. – oshirowanen Oct 18 '22 at 18:07
  • You cannot set a specific color for the status bar icons, that happens based on the background color, but that also depends on the Theme. You can only set the Theme of the MainActivity, e.g. to a Light version as described here: https://montemagno.com/setting-android-status-bar-background-icon-colors/ – Julian Oct 18 '22 at 18:16
  • @oshirowanen I've updated the answer, if you would like to try option 2, which also sets the status bar theme to have a darker tint for the icons – Julian Oct 18 '22 at 18:33
  • 1
    It seems `SystemUiVisibility` is obsolete in your option 2. What would the none obsolete version be? – oshirowanen Oct 18 '22 at 18:45
  • Just updated it, it depends on the Target API – Julian Oct 18 '22 at 18:46
  • For some reason, I can't get the above options to work when using API 33. – oshirowanen Oct 29 '22 at 11:35
  • @oshirowanen can you elaborate? What exactly doesn't work for you? What have you tried? I'm using the StatusBarColor in one of my own apps and it works fine for me. Not sure about the splash screen, though. – Julian Oct 29 '22 at 11:44
  • When I try Option 1 and set the following values: #ff0000 #00ff00 #00ffff It always shows the value in colorPrimaryDark no matter if the device theme is set to light or dark. I'll post details about the other options below. – oshirowanen Oct 29 '22 at 11:52
  • When I try Option 2, I get 1 error and 1 warning. CS0117 and CS0618. – oshirowanen Oct 29 '22 at 11:56
  • When I try Option 3, I can't get very far because after searching the entire solution, styles.xml does not exist. It also does not exist under Platforms/Android/Resources/values. – oshirowanen Oct 29 '22 at 12:01
  • You didn't specify previously (in the beginning, when you asked the question for the first time) that you wanted this to be dependent on the theme. You've only added that information today, right? Options 1 and 3 won't help you if it is supposed to be dynamic. Regarding the `styles.xml`, you will need to add that manually, if it doesn't exist yet. I'll update my answer once I have an updated solution. – Julian Oct 29 '22 at 12:09
  • 1
    You're 100% right, I ended up adding the extra details regarding the system theme as all the solutions I was trying were not working, so I thought I need to give extra detail. – oshirowanen Oct 29 '22 at 12:32
  • 1
    @oshirowanen I just updated my answer. This approach also solved it for my own app. Basically, you need to change the `Maui.SplashTheme` and change its background color – Julian Oct 29 '22 at 15:25
  • 2
    That works really well, thanks! I added `true` to the styles.xml files and `false` to the night version, to change the text/icon color accordingly based on the system theme. – oshirowanen Oct 29 '22 at 17:00
  • Just 1 hopefully tiny issues. After the splash screen, if I change the system theme from light to dark or dark to light without restarting the app, the statusbar color does not change. I have to restart the app to force a statusbar color change after changing the system theme from dark to light or light to dark. Any idea how to fix this issues? – oshirowanen Oct 29 '22 at 17:02
  • Yes, you should still do what I wrote in the ***Manipulate StatusBarColor at runtime*** section, at least the part about the system bar visibility. For me, it works well with that. However, it depends on whether the user changes the system theme or the app theme, as those are two different things. If the system's theme changes and you want to react to it, you'll need to subscribe to them: https://learn.microsoft.com/en-us/dotnet/maui/user-interface/system-theme-changes – Julian Oct 29 '22 at 17:04
  • @oshirowanen I've added some links about app themes and how to respond to changes. – Julian Oct 29 '22 at 17:08
  • Thank you for all the help. I'll accept the answer and start a new question to help resolve the remaining issues. Thanks again. I have to wait 17 hours to award the bounty. – oshirowanen Oct 29 '22 at 18:21
0

After carefully checking the last answer by @Julian , and super thanks to him for making me come to the better solution (and faster one) You just need to edit the project file itself, you will find a MauiIcon element that contains both the full color of the screen (including the status bar) and the color around the application icon (if you want). Example:

<ItemGroup>
    <!-- App Icon -->
    <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />

Full link that explains this is here: https://blog.ewers-peters.de/lets-customize-the-splash-screen-of-a-maui-app (note that it is still the same author of the answer here, but looks like he got updated or something and posted the updates over that blog)