Controlling iOS StatusBar in Xamarin.Forms

On iOS there is this system StatusBar at the top of the screen that shows the battery level, time etc. This is how to control it in Xamarin.Forms

Controlling iOS StatusBar in Xamarin.Forms
Photo by Adrien / Unsplash

On iOS there is this system StatusBar at the top of the screen that shows the battery level, time etc.

One of the common request from designers is to be able to have a transparent NavigationBar and StatusBar and control the StatusBar text color :

  • white text on dark background
  • black text on light background

The most common way of doing this in Xamarin.Forms is to set the BackgroundColor of the NavigationBar and set StatusBarTextColorMode to MatchNavigationBarTextLuminosity. That will adjust the color of the status bar's text automatically. Now all this is fine, until you don't want to display any NavigationBar! Sometimes you want your content to be displayed full screen.

I did a little Xamarin.Forms implementation of that :

First on the Xamarin.Forms side

Hide NavigationBar

As stated in the introduction we don't want to display any NavigationBar :

NavigationPage.HasNavigationBar="False"

Define the available StatusBarStyle

I isolated 4 cases :

public enum StatusBarStyle
{
    Default,
    // Will behave as normal. 
    // White text on black NavigationBar/in iOS Dark mode and 
    // Black text on white NavigationBar/in iOS Light mode
    DarkText,
    // Will switch the color of content of StatusBar to black. 
    WhiteText,
    // Will switch the color of content of StatusBar to white. 
    Hidden
    // Will hide the StatusBar
}

Create an Attached BindableProperty

Attached BindableProperties are super useful. See some documentation about it :

public static class StatusBar
{
    public static readonly BindableProperty StatusBarStyleProperty = BindableProperty.CreateAttached(
        "StatusBarStyle",
        typeof(StatusBarStyle), 
        typeof(Page),
        StatusBarStyle.Default);

    public static void SetStatusBarStyle(BindableObject page, StatusBarStyle value) => page.SetValue(StatusBarStyleProperty, value);
    public static IPlatformElementConfiguration<iOS, Page> SetStatusBarStyle(this IPlatformElementConfiguration<iOS, Page> config, StatusBarStyle value)
    {
        SetStatusBarStyle(config.Element, value);
        return config;
    }

    public static StatusBarStyle GetStatusBarStyle(BindableObject page) => (StatusBarStyle) page.GetValue(StatusBarStyleProperty);
    public static StatusBarStyle GetStatusBarStyle(this IPlatformElementConfiguration<iOS, Page> config) => GetStatusBarStyle(config.Element);

}

This allows us to add to any Xamarin.Forms Page :

<ContentPage ...
    statusBar:StatusBar.StatusBarStyle="WhiteText"/>
<ContentPage ...
    statusBar:StatusBar.StatusBarStyle="DarkText"/>
<ContentPage ...
    statusBar:StatusBar.StatusBarStyle="Hidden"/>

On the iOS Native side

The .plist

In the Info.plist file you need to add the following lines :

<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>

The custom PageRenderer

We need iOS to retrieve that attached property and react to it.

Since iOS is embracing the new Dark Mode, the SDK exposes this : https://developer.apple.com/documentation/uikit/uistatusbarstyle

To use that native API I decided to create a custom page renderer  :

[assembly: ExportRenderer(typeof(Page), typeof(StatusBarRendrerer))]
namespace Namespace
{
    public class StatusBarRendrerer : PageRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);
            SetStatusBarStyle(StatusBar.GetStatusBarStyle(Element));
        }

        private void SetStatusBarStyle(StatusBarStyle statusBarStyle)
        {
            switch (statusBarStyle)
            {
                case StatusBarStyle.DarkText:
                    UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.DarkContent, true);
                    UIApplication.SharedApplication.SetStatusBarHidden(false, true);
                    break;
                case StatusBarStyle.WhiteText:
                    UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, true);
                    UIApplication.SharedApplication.SetStatusBarHidden(false, true);
                    break;
                case StatusBarStyle.Hidden:
                    UIApplication.SharedApplication.SetStatusBarHidden(true, true);
                    break;
                case StatusBarStyle.Default:
                default:
                    UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.Default, true);
                    UIApplication.SharedApplication.SetStatusBarHidden(false, true);
                    break;
            }

            SetNeedsStatusBarAppearanceUpdate();
        }
    }
}
Make sure you run this code on XCode 13 and above because UIStatusBarStyle.DarkContent is not available below

Sample

You can see how this can be implemented in the StatusBar section of my Xamarin-Developer-Sample

Hope it helped 😉