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
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 :
- https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/attached-properties
- https://codemilltech.com/attached-properties-what-are-they-good-for/
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 😉