Skip to content

Commit

Permalink
Update a tabbar with gradient on app theme change
Browse files Browse the repository at this point in the history
  • Loading branch information
kubaflo committed Aug 25, 2024
1 parent c156658 commit 8c7043a
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class NavigationRenderer : UINavigationController, INavigationViewHandler
bool _hasNavigationBar;
UIImage _defaultNavBarShadowImage;
UIImage _defaultNavBarBackImage;
Brush _currentBarBackgroundBrush;
Color _currentBarBackgroundColor;
bool _disposed;
IMauiContext _mauiContext;
IMauiContext MauiContext => _mauiContext;
Expand Down Expand Up @@ -257,6 +259,12 @@ protected override void Dispose(bool disposing)
_secondaryToolbar.RemoveFromSuperview();
_secondaryToolbar.Dispose();
_secondaryToolbar = null;

if(_currentBarBackgroundBrush is SolidColorBrush scb)
scb.InvalidateSolidColorBrushRequested -= OnBarBackgroundChanged;

_currentBarBackgroundBrush = null;
_currentBarBackgroundColor = null;

_parentFlyoutPage = null;
Current = null; // unhooks events
Expand Down Expand Up @@ -707,22 +715,42 @@ void UpdateBackgroundColor()
View.BackgroundColor = color;
}

void OnBarBackgroundChanged(object sender, EventArgs e)
{
RefreshBarBackground();
}

void UpdateBarBackground()
{
var barBackgroundColor = NavPage.BarBackgroundColor;
var barBackgroundBrush = NavPage.BarBackground;
if(_currentBarBackgroundBrush is SolidColorBrush oldSolidColorBrush)
{
oldSolidColorBrush.Parent = null;
oldSolidColorBrush.InvalidateSolidColorBrushRequested -= OnBarBackgroundChanged;
}

_currentBarBackgroundColor = NavPage.BarBackgroundColor;
_currentBarBackgroundBrush = NavPage.BarBackground;

// if the brush has a solid color, treat it as a Color so we can compute the alpha value
if (NavPage.BarBackground is SolidColorBrush scb)
if (_currentBarBackgroundBrush is SolidColorBrush newSolidColorBrush)
{
barBackgroundColor = scb.Color;
barBackgroundBrush = null;
newSolidColorBrush.Parent = NavPage;
newSolidColorBrush.InvalidateSolidColorBrushRequested += OnBarBackgroundChanged;
_currentBarBackgroundColor = newSolidColorBrush.Color;
}

RefreshBarBackground();
}

void RefreshBarBackground()
{
if (_currentBarBackgroundBrush is SolidColorBrush newSolidColorBrush)
_currentBarBackgroundColor = newSolidColorBrush.Color;

if (OperatingSystem.IsIOSVersionAtLeast(13) || OperatingSystem.IsMacCatalystVersionAtLeast(13))
{
var navigationBarAppearance = NavigationBar.StandardAppearance;
if (barBackgroundColor is null)
if (_currentBarBackgroundColor is null)
{
navigationBarAppearance.ConfigureWithOpaqueBackground();
navigationBarAppearance.BackgroundColor = Maui.Platform.ColorExtensions.BackgroundColor;
Expand All @@ -732,17 +760,17 @@ void UpdateBarBackground()
}
else
{
if(barBackgroundColor?.Alpha < 1f)
if(_currentBarBackgroundColor?.Alpha < 1f)
navigationBarAppearance.ConfigureWithTransparentBackground();
else
navigationBarAppearance.ConfigureWithOpaqueBackground();

navigationBarAppearance.BackgroundColor = barBackgroundColor.ToPlatform();
navigationBarAppearance.BackgroundColor = _currentBarBackgroundColor.ToPlatform();
}

if (barBackgroundBrush is not null)
if (_currentBarBackgroundBrush is not null && _currentBarBackgroundBrush is not SolidColorBrush)
{
var backgroundImage = NavigationBar.GetBackgroundImage(barBackgroundBrush);
var backgroundImage = NavigationBar.GetBackgroundImage(_currentBarBackgroundBrush);

navigationBarAppearance.BackgroundImage = backgroundImage;
}
Expand All @@ -753,18 +781,18 @@ void UpdateBarBackground()
}
else
{
if(barBackgroundColor?.Alpha == 0f)
if(_currentBarBackgroundColor?.Alpha == 0f)
{
NavigationBar.SetTransparentNavigationBar();
}
else
{
// Set navigation bar background color
NavigationBar.BarTintColor = barBackgroundColor == null
NavigationBar.BarTintColor = _currentBarBackgroundColor == null
? UINavigationBar.Appearance.BarTintColor
: barBackgroundColor.ToPlatform();
: _currentBarBackgroundColor.ToPlatform();

var backgroundImage = NavigationBar.GetBackgroundImage(barBackgroundBrush);
var backgroundImage = NavigationBar.GetBackgroundImage(_currentBarBackgroundBrush);
NavigationBar.SetBackgroundImage(backgroundImage, UIBarMetrics.Default);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class TabbedRenderer : UITabBarController, IPlatformViewHandler
UITabBarAppearance _tabBarAppearance;
WeakReference<VisualElement> _element;

Brush _currentBarBackground;

IMauiContext MauiContext => _mauiContext;
public static IPropertyMapper<TabbedPage, TabbedRenderer> Mapper = new PropertyMapper<TabbedPage, TabbedRenderer>(TabbedViewHandler.ViewMapper);
public static CommandMapper<TabbedPage, TabbedRenderer> CommandMapper = new CommandMapper<TabbedPage, TabbedRenderer>(TabbedViewHandler.ViewCommandMapper);
Expand Down Expand Up @@ -360,9 +362,26 @@ void UpdateBarBackground()
if (Tabbed is not TabbedPage tabbed || TabBar == null)
return;

var barBackground = tabbed.BarBackground;
if(_currentBarBackground is GradientBrush oldBarBackground)
{
oldBarBackground.Parent = null;
oldBarBackground.InvalidateGradientBrushRequested -= OnBarBackgroundChanged;
}

_currentBarBackground = tabbed.BarBackground;

TabBar.UpdateBackground(barBackground);
if(_currentBarBackground is GradientBrush newGradientBrush)
{
newGradientBrush.Parent = tabbed;
newGradientBrush.InvalidateGradientBrushRequested += OnBarBackgroundChanged;
}

TabBar.UpdateBackground(_currentBarBackground);
}

void OnBarBackgroundChanged(object sender, EventArgs e)
{
TabBar.UpdateBackground(_currentBarBackground);
}

void UpdateBarTextColor()
Expand Down
22 changes: 22 additions & 0 deletions src/Controls/src/Core/Platform/Android/TabbedPageManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,30 @@ internal void UpdateBarBackground()
if (_currentBarBackground == Element.BarBackground)
return;

if(_currentBarBackground is GradientBrush oldGradientBrush)
{
oldGradientBrush.Parent = null;
oldGradientBrush.InvalidateGradientBrushRequested -= OnBarBackgroundChanged;
}

_currentBarBackground = Element.BarBackground;

if(_currentBarBackground is GradientBrush newGradientBrush)
{
newGradientBrush.Parent = Element;
newGradientBrush.InvalidateGradientBrushRequested += OnBarBackgroundChanged;
}

RefreshBarBackground();
}

void OnBarBackgroundChanged(object sender, EventArgs e)
{
RefreshBarBackground();
}

void RefreshBarBackground()
{
if (IsBottomTabPlacement)
_bottomNavigationView.UpdateBackground(_currentBarBackground);
else
Expand Down
23 changes: 23 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue24356.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue24356"
xmlns:ns="clr-namespace:Maui.Controls.Sample.Issues">
<TabbedPage.BarBackground>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="{AppThemeBinding Light=Red, Dark=Brown}"
Offset="0.0" />
<GradientStop Color="{AppThemeBinding Light=White, Dark=Black}"
Offset="0.5" />
<GradientStop Color="{AppThemeBinding Light=Red, Dark=Brown}"
Offset="1.0" />
</LinearGradientBrush>
</TabbedPage.BarBackground>
<ContentPage Title="Tab 1">
<Grid>
<Label IsVisible="{AppThemeBinding Light=True, Dark=False}" AutomationId="lightThemeLabel" Text="Light theme"/>
<Label IsVisible="{AppThemeBinding Light=False, Dark=True}" AutomationId="darkThemeLabel" Text="Dark theme"/>
</Grid>
</ContentPage>
<ContentPage Title="Tab 2"/>
</TabbedPage>
11 changes: 11 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue24356.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 24356, "AppThemeBinding BarBackground with Brush in NavigationPage and TabbedPage not working", PlatformAffected.All)]
public partial class Issue24356 : TabbedPage
{
public Issue24356()
{
InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#if ANDROID || IOS
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue24356 : _IssuesUITest
{
public Issue24356(TestDevice testDevice) : base(testDevice)
{
}

public override string Issue => "AppThemeBinding BarBackground with Brush in NavigationPage and TabbedPage not working";

[Test]
[Category(UITestCategories.TabbedPage)]
public void GradientInTabBarShouldChange()
{
try {
App.WaitForElement("lightThemeLabel");
App.SetDarkTheme();
App.WaitForElement("darkThemeLabel");
VerifyScreenshot();
}
finally
{
App.SetLightTheme();
}
}
}
}
#endif

0 comments on commit 8c7043a

Please sign in to comment.