From 6167bd6524c90f4fdb245f231b498b465e587540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez=20Ruiz?= Date: Wed, 10 Nov 2021 11:35:04 +0100 Subject: [PATCH] Fix Shell NavigationBar and TabBar color issues on iOS 15 --- src/Compatibility/Core/src/iOS/Forms.cs | 11 ++ .../SafeShellTabBarAppearanceTracker.cs | 109 +++++++++++++++--- .../Renderers/ShellNavBarAppearanceTracker.cs | 77 ++++++++++--- 3 files changed, 167 insertions(+), 30 deletions(-) diff --git a/src/Compatibility/Core/src/iOS/Forms.cs b/src/Compatibility/Core/src/iOS/Forms.cs index 59037908947a..2e164803e9ee 100644 --- a/src/Compatibility/Core/src/iOS/Forms.cs +++ b/src/Compatibility/Core/src/iOS/Forms.cs @@ -49,6 +49,7 @@ public static class Forms static bool? s_isiOS12OrNewer; static bool? s_isiOS13OrNewer; static bool? s_isiOS14OrNewer; + static bool? s_isiOS15OrNewer; static bool? s_respondsTosetNeedsUpdateOfHomeIndicatorAutoHidden; internal static bool IsiOS9OrNewer @@ -112,6 +113,16 @@ internal static bool IsiOS14OrNewer } } + internal static bool IsiOS15OrNewer + { + get + { + if (!s_isiOS15OrNewer.HasValue) + s_isiOS15OrNewer = UIDevice.CurrentDevice.CheckSystemVersion(15, 0); + return s_isiOS15OrNewer.Value; + } + } + // Once we get essentials/cg converted to using startup.cs // we will delete all the renderer code inside this file internal static void RenderersRegistered() diff --git a/src/Compatibility/Core/src/iOS/Renderers/SafeShellTabBarAppearanceTracker.cs b/src/Compatibility/Core/src/iOS/Renderers/SafeShellTabBarAppearanceTracker.cs index 39e913406aa4..387b3a06596a 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/SafeShellTabBarAppearanceTracker.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/SafeShellTabBarAppearanceTracker.cs @@ -26,8 +26,8 @@ public virtual void SetAppearance(UITabBarController controller, ShellAppearance { IShellAppearanceElement appearanceElement = appearance; var backgroundColor = appearanceElement.EffectiveTabBarBackgroundColor; - var foregroundColor = appearanceElement.EffectiveTabBarForegroundColor; // currently unused - var disabledColor = appearanceElement.EffectiveTabBarDisabledColor; // unused on iOS + var foregroundColor = appearanceElement.EffectiveTabBarForegroundColor; // Currently unused + var disabledColor = appearanceElement.EffectiveTabBarDisabledColor; // Unused on iOS var unselectedColor = appearanceElement.EffectiveTabBarUnselectedColor; var titleColor = appearanceElement.EffectiveTabBarTitleColor; @@ -44,17 +44,11 @@ public virtual void SetAppearance(UITabBarController controller, ShellAppearance _defaultUnselectedTint = tabBar.UnselectedItemTintColor; } } - - if (backgroundColor != null) - tabBar.BarTintColor = backgroundColor.ToUIColor(); - if (titleColor != null) - tabBar.TintColor = titleColor.ToUIColor(); - - if (operatingSystemSupportsUnselectedTint) - { - if (unselectedColor != null) - tabBar.UnselectedItemTintColor = unselectedColor.ToUIColor(); - } + + if (Forms.IsiOS15OrNewer) + UpdateiOS15TabBarAppearance(controller, appearance); + else + UpdateTabBarAppearance(controller, appearance); } public virtual void UpdateLayout(UITabBarController controller) @@ -62,6 +56,7 @@ public virtual void UpdateLayout(UITabBarController controller) } #region IDisposable Support + protected virtual void Dispose(bool disposing) { } @@ -70,7 +65,95 @@ public void Dispose() { Dispose(true); } + #endregion + void UpdateiOS15TabBarAppearance(UITabBarController controller, ShellAppearance appearance) + { + IShellAppearanceElement appearanceElement = appearance; + + var tabBar = controller.TabBar; + + var tabBarAppearance = new UITabBarAppearance(); + tabBarAppearance.ConfigureWithOpaqueBackground(); + + // Set TabBarBackgroundColor + var tabBarBackgroundColor = appearanceElement.EffectiveTabBarBackgroundColor; + + if (tabBarBackgroundColor != null) + tabBarAppearance.BackgroundColor = tabBarBackgroundColor.ToUIColor(); + + // Set TabBarTitleColor + var tabBarTitleColor = appearanceElement.EffectiveTabBarTitleColor; + + // Update colors for all variations of the appearance to also make it work for iPads, etc. which use different layouts for the tabbar + // Also, set ParagraphStyle explicitly. This seems to be an iOS bug. If we don't do this, tab titles will be truncat... + if (tabBarTitleColor != null) + { + tabBarAppearance.StackedLayoutAppearance.Normal.TitleTextAttributes = tabBarAppearance.StackedLayoutAppearance.Selected.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarTitleColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.StackedLayoutAppearance.Normal.IconColor = tabBarAppearance.StackedLayoutAppearance.Selected.IconColor = tabBarTitleColor.ToUIColor(); + + tabBarAppearance.InlineLayoutAppearance.Normal.TitleTextAttributes = tabBarAppearance.InlineLayoutAppearance.Selected.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarTitleColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.InlineLayoutAppearance.Normal.IconColor = tabBarAppearance.InlineLayoutAppearance.Selected.IconColor = tabBarTitleColor.ToUIColor(); + + tabBarAppearance.CompactInlineLayoutAppearance.Normal.TitleTextAttributes = tabBarAppearance.CompactInlineLayoutAppearance.Selected.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarTitleColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.CompactInlineLayoutAppearance.Normal.IconColor = tabBarAppearance.CompactInlineLayoutAppearance.Selected.IconColor = tabBarTitleColor.ToUIColor(); + } + + //Set TabBarUnselectedColor + var tabBarUnselectedColor = appearanceElement.EffectiveTabBarUnselectedColor; + + if (tabBarUnselectedColor != null) + { + tabBarAppearance.StackedLayoutAppearance.Normal.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarUnselectedColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.StackedLayoutAppearance.Normal.IconColor = tabBarUnselectedColor.ToUIColor(); + + tabBarAppearance.InlineLayoutAppearance.Normal.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarUnselectedColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.InlineLayoutAppearance.Normal.IconColor = tabBarUnselectedColor.ToUIColor(); + + tabBarAppearance.CompactInlineLayoutAppearance.Normal.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarUnselectedColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.CompactInlineLayoutAppearance.Normal.IconColor = tabBarUnselectedColor.ToUIColor(); + } + + // Set TabBarDisabledColor + var tabBarDisabledColor = appearanceElement.EffectiveTabBarDisabledColor; + + if (tabBarDisabledColor != null) + { + tabBarAppearance.StackedLayoutAppearance.Disabled.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarDisabledColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.StackedLayoutAppearance.Disabled.IconColor = tabBarDisabledColor.ToUIColor(); + + tabBarAppearance.InlineLayoutAppearance.Disabled.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarDisabledColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.InlineLayoutAppearance.Disabled.IconColor = tabBarDisabledColor.ToUIColor(); + + tabBarAppearance.CompactInlineLayoutAppearance.Disabled.TitleTextAttributes = new UIStringAttributes { ForegroundColor = tabBarDisabledColor.ToUIColor(), ParagraphStyle = NSParagraphStyle.Default }; + tabBarAppearance.CompactInlineLayoutAppearance.Disabled.IconColor = tabBarDisabledColor.ToUIColor(); + } + + tabBar.StandardAppearance = tabBar.ScrollEdgeAppearance = tabBarAppearance; + } + + void UpdateTabBarAppearance(UITabBarController controller, ShellAppearance appearance) + { + IShellAppearanceElement appearanceElement = appearance; + var backgroundColor = appearanceElement.EffectiveTabBarBackgroundColor; + var unselectedColor = appearanceElement.EffectiveTabBarUnselectedColor; + var titleColor = appearanceElement.EffectiveTabBarTitleColor; + + var tabBar = controller.TabBar; + + if (backgroundColor != null) + tabBar.BarTintColor = backgroundColor.ToUIColor(); + if (titleColor.IsDefault != null) + tabBar.TintColor = titleColor.ToUIColor(); + + bool operatingSystemSupportsUnselectedTint = Forms.IsiOS10OrNewer; + + if (operatingSystemSupportsUnselectedTint) + { + if (unselectedColor.IsDefault != null) + tabBar.UnselectedItemTintColor = unselectedColor.ToUIColor(); + } + } } } \ No newline at end of file diff --git a/src/Compatibility/Core/src/iOS/Renderers/ShellNavBarAppearanceTracker.cs b/src/Compatibility/Core/src/iOS/Renderers/ShellNavBarAppearanceTracker.cs index c7056d648e63..b3eb3c2ce627 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/ShellNavBarAppearanceTracker.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/ShellNavBarAppearanceTracker.cs @@ -23,17 +23,14 @@ public void ResetAppearance(UINavigationController controller) if (_defaultTint != null) { var navBar = controller.NavigationBar; + navBar.BarTintColor = _defaultBarTint; navBar.TintColor = _defaultTint; navBar.TitleTextAttributes = _defaultTitleAttributes; } } public void SetAppearance(UINavigationController controller, ShellAppearance appearance) - { - var background = appearance.BackgroundColor; - var foreground = appearance.ForegroundColor; - var titleColor = appearance.TitleColor; - + { var navBar = controller.NavigationBar; if (_defaultTint == null) @@ -43,20 +40,14 @@ public void SetAppearance(UINavigationController controller, ShellAppearance app _defaultTitleAttributes = navBar.TitleTextAttributes; } - if (background != null) - navBar.BarTintColor = background.ToUIColor(); - if (foreground != null) - navBar.TintColor = foreground.ToUIColor(); - if (titleColor != null) - { - navBar.TitleTextAttributes = new UIStringAttributes - { - ForegroundColor = titleColor.ToUIColor() - }; - } + if (Forms.IsiOS15OrNewer) + UpdateiOS15NavigationBarAppearance(controller, appearance); + else + UpdateNavigationBarAppearance(controller, appearance); } #region IDisposable Support + protected virtual void Dispose(bool disposing) { } @@ -90,6 +81,58 @@ public virtual void SetHasShadow(UINavigationController controller, bool hasShad navigationBar.Layer.ShadowOpacity = _shadowOpacity; } } + #endregion + + void UpdateiOS15NavigationBarAppearance(UINavigationController controller, ShellAppearance appearance) + { + var navBar = controller.NavigationBar; + + var navigationBarAppearance = new UINavigationBarAppearance(); + navigationBarAppearance.ConfigureWithOpaqueBackground(); + + navBar.Translucent = false; + + // Set ForegroundColor + var foreground = appearance.ForegroundColor; + + if (foreground != null) + navBar.TintColor = foreground.ToUIColor(); + + // Set BackgroundColor + var background = appearance.BackgroundColor; + + if (background != null) + navigationBarAppearance.BackgroundColor = background.ToUIColor(); + + // Set TitleColor + var titleColor = appearance.TitleColor; + + if (titleColor != null) + navigationBarAppearance.TitleTextAttributes = new UIStringAttributes() { ForegroundColor = titleColor.ToUIColor() }; + + navBar.StandardAppearance = navBar.ScrollEdgeAppearance = navigationBarAppearance; + } + + void UpdateNavigationBarAppearance(UINavigationController controller, ShellAppearance appearance) + { + var background = appearance.BackgroundColor; + var foreground = appearance.ForegroundColor; + var titleColor = appearance.TitleColor; + + var navBar = controller.NavigationBar; + + if (background != null) + navBar.BarTintColor = background.ToUIColor(); + if (foreground != null) + navBar.TintColor = foreground.ToUIColor(); + if (titleColor != null) + { + navBar.TitleTextAttributes = new UIStringAttributes + { + ForegroundColor = titleColor.ToUIColor() + }; + } + } } -} +} \ No newline at end of file