问题
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 ?
回答1:
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
回答2:
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());
}
回答3:
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;
来源:https://stackoverflow.com/questions/58441077/how-to-change-the-status-bar-color-without-a-navigation-page