如何在没有导航页面的情况下更改状态栏颜色

G.M*_*ich 5 c# xamarin.ios xamarin.android xamarin xamarin.forms

我想更改某些视图上的状态栏颜色。

我找到了这个解决方案https://github.com/yuv4ik/XFDynamicStatusBarAppearance

但它仅适用于 NavigationPage。

我不需要从我的应用程序导航页面...

    public App()
    {
        InitializeComponent();

        MainPage = new MainPage();
    }
Run Code Online (Sandbox Code Playgroud)

这是我的尝试...

    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;
        }
    };
Run Code Online (Sandbox Code Playgroud)

如何更改状态栏颜色?

G.M*_*ich 11

这是我在两个平台上的工作解决方案......

public interface IStatusBarStyleManager
{
    void SetColoredStatusBar(string hexColor);
    void SetWhiteStatusBar();
}
Run Code Online (Sandbox Code Playgroud)

使用此行设置状态栏颜色

DependencyService.Get<IStatusBarStyleManager>().SetColoredStatusBar("#2196F3");
Run Code Online (Sandbox Code Playgroud)

或者你可以用黑色字体颜色保持白色

DependencyService.Get<IStatusBarStyleManager>().SetWhiteStatusBar();
Run Code Online (Sandbox Code Playgroud)

安卓

[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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

帖子更新以支持 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

完整的工作示例在这里https://github.com/georgemichailou/ShaXam


Мак*_*вой 5

@Cherry Bu 的回答 - MSFT 很棒,但有点过时了。SystemUiVisibility在Android 11中已过时,因此这里更新StatusBarStyleManager兼容新的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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

旁注:如果您还想更改状态栏的颜色,则需要更改以下行:

  • currentWindow.DecorView.SystemUiVisibility = isLight ? (StatusBarVisibility)(SystemUiFlags.LightStatusBar | SystemUiFlags.LightNavigationBar) : 0;
  • var lightStatusBars = isLight ? WindowInsetsControllerAppearance.LightStatusBars | WindowInsetsControllerAppearance.LightNavigationBars : 0;

更新 - 2021 年夏季

此代码(或多或少)现在是 Xamarin.CommunityToolkit 的一部分: https: //github.com/xamarin/XamarinCommunityToolkit/pull/812。我建议从那里使用它,如果出现任何问题,请提出问题,这样每个人都会得到解决。

目前 XCT 针对 Android 10,因此没有 Android 11 相关代码,但是当此逻辑将迁移到CommunityToolkit.Maui时,Android 11 逻辑也将被添加(XCT 和 CT.MAUI 在任何 Android 版本上都可以正常工作,只需想要指出代码差异)

  • @ledragon 您好,更新了答案以表明该代码现在是 XCT 的一部分。您可以在那里打开一个问题吗? (2认同)