Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.
This repository was archived by the owner on May 1, 2024. It is now read-only.

[Enhancement] Add BarStyleManager to manage navigation and status bar color #708

@maxkoshevoi

Description

@maxkoshevoi

Summary

Add methods to change status and navigation bar color and appearance (white or dark text color).

API Changes

Here is the interface that I use:

namespace MyProject.Core.Models.InterplatformCommunication
{
    public interface IBarStyleManager
    {
        void SetStatusBarColor(string hexColor);

        void SetNavigationBarColor(string hexColor);
    }
}

Android implementation (modified SO answer):

Show/Hide code
using Android.Graphics;
using Android.OS;
using Android.Views;
using MyProject.Core.Models.InterplatformCommunication;
using NureTimetable.Droid.Dependences;
using Xamarin.Essentials;
using MyProject.Core.Extensions;

[assembly: Xamarin.Forms.Dependency(typeof(BarStyleManager))]
namespace MyProject.Droid.Dependences
{
    public class BarStyleManager : IBarStyleManager
    {
        public void SetStatusBarColor(string hexColor)
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.M)
            {
                return;
            }

            Color color = Color.ParseColor(hexColor);
            MainThread.BeginInvokeOnMainThread(() =>
            {
                var currentWindow = GetCurrentWindow();
                SetBarAppearance(currentWindow, color == Color.White, null);
                currentWindow.SetStatusBarColor(color);
            });
        }

        public void SetNavigationBarColor(string hexColor)
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.M)
            {
                return;
            }

            Color color = Color.ParseColor(hexColor);
            MainThread.BeginInvokeOnMainThread(() =>
            {
                var currentWindow = GetCurrentWindow();
                SetBarAppearance(currentWindow, null, color == Color.White);
                currentWindow.SetNavigationBarColor(color);
            });
        }

        private static void SetBarAppearance(Window currentWindow, bool? statusBarLight = null, bool? navigationBarLight = null)
        {
            StatusBarVisibility barAppearanceOld = 0;
            WindowInsetsControllerAppearance barAppearanceNew = 0;
            if ((int)Build.VERSION.SdkInt < 30)
            {
#pragma warning disable CS0618 // Type or member is obsolete. Using new API for Sdk 30+
                barAppearanceOld = currentWindow.DecorView.SystemUiVisibility;
#pragma warning restore CS0618 // Type or member is obsolete
            }
            else
            {
                barAppearanceNew = (WindowInsetsControllerAppearance)currentWindow.InsetsController.SystemBarsAppearance;
            }

            if (statusBarLight == true)
            {
                barAppearanceOld = barAppearanceOld.AddFlag((StatusBarVisibility)SystemUiFlags.LightStatusBar);
                barAppearanceNew = barAppearanceNew.AddFlag(WindowInsetsControllerAppearance.LightStatusBars);
            }
            else if (statusBarLight == false)
            {
                barAppearanceOld = barAppearanceOld.RemoveFlag((StatusBarVisibility)SystemUiFlags.LightStatusBar);
                barAppearanceNew = barAppearanceNew.RemoveFlag(WindowInsetsControllerAppearance.LightStatusBars);
            }
            if (navigationBarLight == true)
            {
                barAppearanceOld = barAppearanceOld.AddFlag((StatusBarVisibility)SystemUiFlags.LightNavigationBar);
                barAppearanceNew = barAppearanceNew.AddFlag(WindowInsetsControllerAppearance.LightNavigationBars);
            }
            else if (navigationBarLight == false)
            {
                barAppearanceOld = barAppearanceOld.RemoveFlag((StatusBarVisibility)SystemUiFlags.LightNavigationBar);
                barAppearanceNew = barAppearanceNew.RemoveFlag(WindowInsetsControllerAppearance.LightNavigationBars);
            }
            
            if ((int)Build.VERSION.SdkInt < 30)
            {
#pragma warning disable CS0618 // Type or member is obsolete. Using new API for Sdk 30+
                currentWindow.DecorView.SystemUiVisibility = barAppearanceOld;
#pragma warning restore CS0618 // Type or member is obsolete
            }
            else
            {
                currentWindow.InsetsController?.SetSystemBarsAppearance((int)barAppearanceNew, (int)barAppearanceNew);
            }
        }

        private Window GetCurrentWindow()
        {
            Window window = Platform.CurrentActivity.Window;
            window.ClearFlags(WindowManagerFlags.TranslucentStatus);
            window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
            return window;
        }
    }
}

Intended Use Case

This will be used to more easily customize theme of the application

Who Will Do The Work?

  • I am willing to take this on myself (but only for Android. I have no experience in iOS development and don't have Mac to do it)
  • Just putting this out there for someone to pick up

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature-requestA request for a new feature.needs-approvalFeature request has been submitted but is awaiting final approval. Please do not implement before!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions