Skip to content

Commit

Permalink
BarBackground with Brush in NavigationPage on theme change (dotnet#2…
Browse files Browse the repository at this point in the history
…4429)

* BarBackground with Brush in NavigationPage on theme change

* Added snapshots

* Update NavigationBarBackgroundShouldChange.png

* Update Issue24428.cs

* Updated snapshots

* Typo fix
  • Loading branch information
kubaflo authored Jan 9, 2025
1 parent da0f504 commit 4c05cb8
Show file tree
Hide file tree
Showing 9 changed files with 163 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 @@ -262,6 +264,12 @@ protected override void Dispose(bool disposing)
_secondaryToolbar.RemoveFromSuperview();
_secondaryToolbar.Dispose();
_secondaryToolbar = null;

if(_currentBarBackgroundBrush is GradientBrush gb)
gb.InvalidateGradientBrushRequested -= OnBarBackgroundChanged;

_currentBarBackgroundBrush = null;
_currentBarBackgroundColor = null;

_parentFlyoutPage = null;
Current = null; // unhooks events
Expand Down Expand Up @@ -712,22 +720,44 @@ 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 GradientBrush oldGradientBrush)
{
oldGradientBrush.Parent = null;
oldGradientBrush.InvalidateGradientBrushRequested -= OnBarBackgroundChanged;
}

// 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)
_currentBarBackgroundColor = NavPage.BarBackgroundColor;
_currentBarBackgroundBrush = NavPage.BarBackground;

if (_currentBarBackgroundBrush is GradientBrush newGradientBrush)
{
barBackgroundColor = scb.Color;
barBackgroundBrush = null;
newGradientBrush.Parent = NavPage;
newGradientBrush.InvalidateGradientBrushRequested += OnBarBackgroundChanged;
}

RefreshBarBackground();
}

void RefreshBarBackground()
{
// if the brush has a solid color, treat it as a Color so we can compute the alpha value
if (_currentBarBackgroundBrush is SolidColorBrush newSolidColorBrush)
{
_currentBarBackgroundColor = newSolidColorBrush.Color;
_currentBarBackgroundBrush = null;
}

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 @@ -737,17 +767,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)
{
var backgroundImage = NavigationBar.GetBackgroundImage(barBackgroundBrush);
var backgroundImage = NavigationBar.GetBackgroundImage(_currentBarBackgroundBrush);

navigationBarAppearance.BackgroundImage = backgroundImage;
}
Expand All @@ -758,18 +788,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
33 changes: 32 additions & 1 deletion src/Controls/src/Core/Toolbar/Toolbar.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public partial class Toolbar
List<IMenuItem> _currentMenuItems = new List<IMenuItem>();
List<ToolbarItem> _currentToolbarItems = new List<ToolbarItem>();

Brush _currentBarBackground;

NavigationRootManager? NavigationRootManager =>
Handler?.MauiContext?.GetNavigationRootManager();

Expand Down Expand Up @@ -103,6 +105,35 @@ void UpdateTitleView()
_platformTitleView.Child = (IPlatformViewHandler?)_platformTitleViewHandler;
}

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

_currentBarBackground = BarBackground;

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

RefreshBarBackground();
}

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

void RefreshBarBackground()
{
PlatformView.UpdateBarBackground(this);
}

public static void MapBarTextColor(ToolbarHandler arg1, Toolbar arg2) =>
MapBarTextColor((IToolbarHandler)arg1, arg2);

Expand Down Expand Up @@ -143,7 +174,7 @@ public static void MapBarTextColor(IToolbarHandler arg1, Toolbar arg2)

public static void MapBarBackground(IToolbarHandler arg1, Toolbar arg2)
{
arg1.PlatformView.UpdateBarBackground(arg2);
arg2.UpdateBarBackground();
}

public static void MapBackButtonTitle(IToolbarHandler arg1, Toolbar arg2)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue24428.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<NavigationPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue24428NavPage">
<NavigationPage.BarBackground>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="{AppThemeBinding Light=Red, Dark=Brown}" Offset="0.0" />
<GradientStop Color="{AppThemeBinding Light=Green, Dark=Yellow}" Offset="0.5" />
<GradientStop Color="{AppThemeBinding Light=Red, Dark=Brown}" Offset="1.0" />
</LinearGradientBrush>
</NavigationPage.BarBackground>
</NavigationPage>
39 changes: 39 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue24428.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace Maui.Controls.Sample.Issues
{
[XamlCompilation(XamlCompilationOptions.Compile)]
[Issue(IssueTracker.Github, 24428, "AppThemeBinding BarBackground with GradientBrush in NavigationPage not working", PlatformAffected.All)]
public partial class Issue24428NavPage : NavigationPage
{
public Issue24428NavPage() : base(new Issue24428ContentPage())
{
InitializeComponent();
}
}

public class Issue24428ContentPage : ContentPage
{
public Issue24428ContentPage()
{
var label1 = new Label()
{
AutomationId = "lightThemeLabel",
Text = "Light theme"
};

var label2 = new Label()
{
AutomationId = "darkThemeLabel",
Text = "Dark theme"
};

label1.SetAppTheme(IsVisibleProperty, true, false);
label2.SetAppTheme(IsVisibleProperty, false, true);

Content = new VerticalStackLayout()
{
label1,
label2
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#if ANDROID || IOS
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

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

public override string Issue => "AppThemeBinding BarBackground with GradientBrush in NavigationPage not working";

[Test]
[Category(UITestCategories.Page)]
public void NavigationBarBackgroundShouldChange()
{
try
{
App.WaitForElement("lightThemeLabel");
VerifyScreenshot("NavigationBarBackgroundShouldChangeLightTheme");
App.SetDarkTheme();
App.WaitForElement("darkThemeLabel");
VerifyScreenshot("NavigationBarBackgroundShouldChangeDarkTheme");
}
finally
{
App.SetLightTheme();
}
}
}
}
#endif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4c05cb8

Please sign in to comment.