Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the status bar color without a navigation page

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 ?

like image 896
G.Mich Avatar asked Oct 17 '19 21:10

G.Mich


People also ask

How to change the color of the status bar and navigation bar?

How to change the color of the status bar and navigation bar in a flutter. 1. Using AppBar (Both iOS and Android) Here, in brightness parameter, Brightness.light makes the status bar icons dark while Brightness.dart makes the status bar icon white.

How do I change the color of The navbar text?

The navbar text and the brand text color can be set using the .navbar-text and .navbar-brand classes. These are the inbuilt navigation bar classes that are be overridden by using the same class name. The text color is specified using the color property. /* Modify brand and text color */. .navbar-custom .navbar-brand, .navbar-custom .navbar-text {.

How to override the inbuilt navigation bar classes?

The names of the classes are kept in a manner to override the inbuilt navigation bar classes. The background color is set by directly specifying the background-color property with the color needed. The navbar text and the brand text color can be set using the .navbar-text and .navbar-brand classes.

How to change the color of navigation bar in gravitybox?

To change the color of Navigation bar, open the GravityBox app and go to Navigation bar tweaks to tweak your navigation bar. That’s all! This is very simple and as easy as said.


2 Answers

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

like image 182
G.Mich Avatar answered Oct 20 '22 09:10

G.Mich


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)

like image 41
maxc137 Avatar answered Oct 20 '22 09:10

maxc137