Reputation: 1666
I want to change the status bar color on some views.
I found this solution https://github.com/yuv4ik/XFDynamicStatusBarAppearance
but it's working only with NavigationPage.
I don't need from my app Navigation Page ...
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
Here is my try ...
var statusBarStyleManager = DependencyService.Get<IStatusBarStyleManager>();
MainCarousel.PositionChanged += (sender, e) =>
{
switch (e.CurrentPosition)
{
case 1:
Device.BeginInvokeOnMainThread(() =>
{
Xamarin.Forms.Application.Current.MainPage.SetValue(Xamarin.Forms.NavigationPage.BarBackgroundColorProperty, Color.DarkCyan);
//((Xamarin.Forms.NavigationPage)Xamarin.Forms.Application.Current.MainPage).BarBackgroundColor = Color.DarkCyan;
statusBarStyleManager.SetDarkTheme();
});
break;
case 0:
case 2:
Device.BeginInvokeOnMainThread(() =>
{
Xamarin.Forms.Application.Current.MainPage.SetValue(Xamarin.Forms.NavigationPage.BarBackgroundColorProperty, Color.LightGreen);
statusBarStyleManager.SetLightTheme();
});
break;
default:
break;
}
};
How can I change the status bar color ?
Upvotes: 6
Views: 8680
Reputation: 780
As said by @maxc137, this feature is now available in the Xamarin Community Toolkit. You just have to add the Xamarin.CommunityToolkit package to your projects and set the status bar color like this:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Example.Views.MyPage"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xct:StatusBarEffect.Color="Red"
Title="My Page">
If you want to set the same color across all pages, then set a global implicit style:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
x:Class="Example.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True">
<Setter Property="xct:StatusBarEffect.Color" Value="Red"/>
</Style>
</ResourceDictionary>
</Application.Resources>
Upvotes: 2
Reputation: 2741
Answer from @Cherry Bu - MSFT is great, but a bit outdated. SystemUiVisibility
is obsolete in Android 11, so here is updated StatusBarStyleManager
compatible with new API:
using Android.Graphics;
using Android.OS;
using Android.Views;
using Plugin.CurrentActivity;
using Xamarin.Essentials;
[assembly: Xamarin.Forms.Dependency(typeof(StatusBarStyleManager))]
namespace YourApp.Droid.Dependences
{
public class StatusBarStyleManager : IStatusBarStyleManager
{
public void SetColoredStatusBar(string hexColor)
{
if (Build.VERSION.SdkInt < BuildVersionCodes.M)
{
return;
}
MainThread.BeginInvokeOnMainThread(() =>
{
var currentWindow = GetCurrentWindow();
SetStatusBarIsLight(currentWindow, false);
currentWindow.SetStatusBarColor(Color.ParseColor(hexColor));
currentWindow.SetNavigationBarColor(Color.ParseColor(hexColor));
});
}
public void SetWhiteStatusBar()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.M)
{
return;
}
MainThread.BeginInvokeOnMainThread(() =>
{
var currentWindow = GetCurrentWindow();
SetStatusBarIsLight(currentWindow, true);
currentWindow.SetStatusBarColor(Color.White);
currentWindow.SetNavigationBarColor(Color.White);
});
}
private static void SetStatusBarIsLight(Window currentWindow, bool isLight)
{
if ((int)Build.VERSION.SdkInt < 30)
{
#pragma warning disable CS0618 // Type or member is obsolete. Using new API for Sdk 30+
currentWindow.DecorView.SystemUiVisibility = isLight ? (StatusBarVisibility)(SystemUiFlags.LightStatusBar) : 0;
#pragma warning restore CS0618 // Type or member is obsolete
}
else
{
var lightStatusBars = isLight ? WindowInsetsControllerAppearance.LightStatusBars : 0;
currentWindow.InsetsController?.SetSystemBarsAppearance((int)lightStatusBars, (int)lightStatusBars);
}
}
private Window GetCurrentWindow()
{
Window window = Platform.CurrentActivity.Window;
window.ClearFlags(WindowManagerFlags.TranslucentStatus);
window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
return window;
}
}
}
Side note: if you also want to change color of status bar, here are lines that you need to change:
currentWindow.DecorView.SystemUiVisibility = isLight ? (StatusBarVisibility)(SystemUiFlags.LightStatusBar | SystemUiFlags.LightNavigationBar) : 0;
var lightStatusBars = isLight ? WindowInsetsControllerAppearance.LightStatusBars | WindowInsetsControllerAppearance.LightNavigationBars : 0;
Update - Summer 2021:
This code (more or less) is now part of Xamarin.CommunityToolkit: https://github.com/xamarin/XamarinCommunityToolkit/pull/812. I'd recommend using it from there, and in case of any problems open an issue, so it's fixed for everybody.
Currently XCT targets Android 10, so there's no Android 11 related code, but when this logic will be migrated to CommunityToolkit.Maui, Android 11 logic will be added as well (both XCT and CT.MAUI work just fine on any Android version, just wanted to point out code differences)
Upvotes: 5
Reputation: 1666
Here is my working solution on both platforms ...
public interface IStatusBarStyleManager
{
void SetColoredStatusBar(string hexColor);
void SetWhiteStatusBar();
}
Setup the Status bar color with this line
DependencyService.Get<IStatusBarStyleManager>().SetColoredStatusBar("#2196F3");
or you can keep it white with black font color
DependencyService.Get<IStatusBarStyleManager>().SetWhiteStatusBar();
Android
[assembly: Xamarin.Forms.Dependency(typeof(StatusBarStyleManager))]
namespace ShaXam.Droid.DependencyServices
{
public class StatusBarStyleManager : IStatusBarStyleManager
{
public void SetColoredStatusBar(string hexColor)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.M)
{
Device.BeginInvokeOnMainThread(() =>
{
var currentWindow = GetCurrentWindow();
currentWindow.DecorView.SystemUiVisibility = 0;
currentWindow.SetStatusBarColor(Android.Graphics.Color.ParseColor(hexColor);
});
}
}
public void SetWhiteStatusBar()
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.M)
{
Device.BeginInvokeOnMainThread(() =>
{
var currentWindow = GetCurrentWindow();
currentWindow.DecorView.SystemUiVisibility = (StatusBarVisibility)SystemUiFlags.LightStatusBar;
currentWindow.SetStatusBarColor(Android.Graphics.Color.White);
});
}
}
Window GetCurrentWindow()
{
var window = CrossCurrentActivity.Current.Activity.Window;
// clear FLAG_TRANSLUCENT_STATUS flag:
window.ClearFlags(WindowManagerFlags.TranslucentStatus);
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
return window;
}
}
}
iOS
[assembly: Dependency(typeof(StatusBarStyleManager))]
namespace ShaXam.iOS.DependencyServices
{
public class StatusBarStyleManager : IStatusBarStyleManager
{
public void SetColoredStatusBar(string hexColor)
{
Device.BeginInvokeOnMainThread(() =>
{
UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.BackgroundColor = Color.FromHex(hexColor).ToUIColor();
}
UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, false);
GetCurrentViewController().SetNeedsStatusBarAppearanceUpdate();
});
}
public void SetWhiteStatusBar()
{
Device.BeginInvokeOnMainThread(() =>
{
UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.BackgroundColor = UIColor.White;
}
UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.Default, false);
GetCurrentViewController().SetNeedsStatusBarAppearanceUpdate();
});
}
UIViewController GetCurrentViewController()
{
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
vc = vc.PresentedViewController;
return vc;
}
}
}
POST UPDATED TO SUPPORT THE IOS 13
[assembly: Dependency(typeof(StatusBarStyleManager))]
namespace ShaXam.iOS.DependencyServices
{
public class StatusBarStyleManager : IStatusBarStyleManager
{
public void SetColoredStatusBar(string hexColor)
{
Device.BeginInvokeOnMainThread(() =>
{
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
statusBar.BackgroundColor = Color.FromHex(hexColor).ToUIColor();
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
}
else
{
UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.BackgroundColor = Color.FromHex(hexColor).ToUIColor();
}
}
UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, false);
GetCurrentViewController().SetNeedsStatusBarAppearanceUpdate();
});
}
public void SetWhiteStatusBar()
{
Device.BeginInvokeOnMainThread(() =>
{
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
statusBar.BackgroundColor = UIColor.White;
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
}
else
{
UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.BackgroundColor = UIColor.White;
}
}
UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.DarkContent, false);
GetCurrentViewController().SetNeedsStatusBarAppearanceUpdate();
});
}
UIViewController GetCurrentViewController()
{
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
vc = vc.PresentedViewController;
return vc;
}
}
}
The full working sample is here https://github.com/georgemichailou/ShaXam
Upvotes: 15
Reputation: 10346
You can try add this code in Android platform, OnCreate method:
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
Window.SetStatusBarColor(Android.Graphics.Color.Argb(255, 0, 0, 0)); //here
}
Please note SetStatusBarColor is only supported in API level 21 and up. Therefore, we should check for this before calling SetStatusBarColor.
if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
Window.SetStatusBarColor(...);
}
Update:
Create interface in PCL:
public interface IStatusBarColor
{
void changestatuscolor(string color);
}
Now, Mainactivity implement this interface.
[assembly: Dependency(typeof(demo2.Droid.MainActivity))]
namespace demo2.Droid
{
[Activity(Label = "demo2", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,IStatusBarColor
{
public static Context context;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public void changestatuscolor(string color)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
var c = MainActivity.context as FormsAppCompatActivity;
c?.RunOnUiThread(() => c.Window.SetStatusBarColor(Android.Graphics.Color.ParseColor(color)));
}
}
protected override void OnResume()
{
context = this;
base.OnResume();
}
}
}
In Mainpage, to change status bar color in Button click event.
private void Changecolor_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IStatusBarColor>().changestatuscolor(Color.Red.ToHex());
}
Upvotes: 3