Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions src/Controls/src/Core/Platform/Android/TabbedPageManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
{
menuItem.SetIcon(result.Value);
});
SetupBottomNavigationViewIconColor(page, menuItem, index);
}
else
{
Expand Down Expand Up @@ -652,8 +653,13 @@ int GetItemTextColor(Color customColor, ColorStateList originalColors)
return customColor?.ToPlatform().ToArgb() ?? originalColors?.DefaultColor ?? 0;
}

protected virtual ColorStateList GetItemIconTintColorState()
protected virtual ColorStateList GetItemIconTintColorState(Page page)
{
if (page.IconImageSource is FontImageSource fontImageSource && fontImageSource.Color is not null)
{
return null;
}

if (_orignalTabIconColors is null)
{
_orignalTabIconColors = IsBottomTabPlacement ? _bottomNavigationView.ItemIconTintList : _tabLayout.TabIconTint;
Expand Down Expand Up @@ -773,7 +779,14 @@ void UpdateItemIconColor()
_newTabIconColors = null;

if (IsBottomTabPlacement)
_bottomNavigationView.ItemIconTintList = GetItemIconTintColorState() ?? _orignalTabIconColors;
{
for (int i = 0; i < _bottomNavigationView.Menu.Size(); i++)
{
var menuItem = _bottomNavigationView.Menu.GetItem(i);
var page = Element.Children[i];
SetupBottomNavigationViewIconColor(page, menuItem, i);
}
}
else
{
for (int i = 0; i < _tabLayout.TabCount; i++)
Expand All @@ -785,6 +798,28 @@ void UpdateItemIconColor()
}
}

void SetupBottomNavigationViewIconColor(Page page, IMenuItem menuItem, int i)
{
// Updating the icon color of each BottomNavigationView item individually works correctly.
// This is necessary because `ItemIconTintList` applies the color globally to all items,
// which doesn't allow for per-item customization.
// Currently, there is no modern API that provides the desired behavior.
// Therefore, the obsolete `BottomNavigationItemView` approach is used.
#pragma warning disable XAOBS001 // Type or member is obsolete
if (_bottomNavigationView.GetChildAt(0) is BottomNavigationMenuView menuView)
{
var itemView = menuView.GetChildAt(i) as BottomNavigationItemView;

if (itemView != null && itemView.Id == menuItem.ItemId)
{
ColorStateList colors = GetItemIconTintColorState(page);

itemView.SetIconTintList(colors);
}
}
#pragma warning restore XAOBS001 // Type or member is obsolete
}

internal void UpdateTabItemStyle()
{
Color barItemColor = BarItemColor;
Expand Down Expand Up @@ -830,7 +865,7 @@ void SetIconColorFilter(Page page, TabLayout.Tab tab, bool selected)
if (icon == null)
return;

ColorStateList colors = (page.IconImageSource is FontImageSource fontImageSource && fontImageSource.Color is not null) ? null : GetItemIconTintColorState();
ColorStateList colors = GetItemIconTintColorState(page);
if (colors == null)
ADrawableCompat.SetTintList(icon, null);
else
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.
122 changes: 122 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue29109.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;
using Button = Microsoft.Maui.Controls.Button;

namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 29109, "[Android] Unable to set unselected iconImageSource color when toolbar placement is set to bottom", PlatformAffected.Android)]
public class Issue29109 : TestTabbedPage
{
protected override void Init()
{
// Set the toolbar placement to bottom (android specific)
On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().SetToolbarPlacement(Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.ToolbarPlacement.Bottom);
// Set tab colors
this.SelectedTabColor = Colors.Red;
this.UnselectedTabColor = Colors.Gray;

// Add tabs
this.Children.Add(new Issue29109Tab1());
this.Children.Add(new Issue29109Tab2());
this.Children.Add(new Issue29109Tab3());
}
}

public class Issue29109Tab1 : ContentPage
{
public Issue29109Tab1()
{
//If no FontImageSource color is given, tab icon should be applied based on the SelectedTabColor and UnselectedTabColor.
IconImageSource = new FontImageSource
{
FontFamily = "Ion",
Glyph = "\uf47e",
Size = 15
};
Button button = new Button
{
Text = "Change Tab Icon Color",
BackgroundColor = Colors.Green,
TextColor = Colors.White
};
button.AutomationId = "Button";
button.Clicked += (s, e) =>
{
//If the FontImageSource color is given, the tab icon color should be applied solely based on the specified color, regardless of the SelectedTabColor or UnselectedTabColor.
(this.IconImageSource as FontImageSource).Color = Colors.Orange;
};
Title = "Tab 1";
var verticalStackLayout = new VerticalStackLayout
{
VerticalOptions = LayoutOptions.Center,
Children = {
new Label
{
HorizontalOptions = LayoutOptions.Center,
Text = "Tab 1"
},
button
}

};
Content = verticalStackLayout;
}
}

public class Issue29109Tab2 : ContentPage
{
public Issue29109Tab2()
{
//The FontImageSource color is given. So, the tab icon color should be applied based solely on the given color, regardless of the selected tab or unselected tab color.
IconImageSource = new FontImageSource
{
FontFamily = "Ion",
Glyph = "\uf47e",
Color = Colors.DodgerBlue,
Size = 15
};

Title = "Tab 2";
var verticalStackLayout = new VerticalStackLayout
{
VerticalOptions = LayoutOptions.Center,
Children =
{
new Label
{
HorizontalOptions = LayoutOptions.Center,
Text = "Tab 2"
},
}
};
Content = verticalStackLayout;
}
}
public class Issue29109Tab3 : ContentPage
{
public Issue29109Tab3()
{
//The FontImageSource color is given. So, the icon color should be applied based solely on the given color, regardless of the selected tab or unselected tab color.
IconImageSource = new FontImageSource
{
FontFamily = "Ion",
Glyph = "\uf47e",
Color = Colors.Green,
Size = 15
};

Title = "Tab 3";
var verticalStackLayout = new VerticalStackLayout
{
VerticalOptions = LayoutOptions.Center,
Children =
{
new Label
{
HorizontalOptions = LayoutOptions.Center,
Text = "Tab 3"
},
}
};
Content = verticalStackLayout;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#if ANDROID
//Since bottom tab placement is specific to Android, I enabled it only for Android: https://learn.microsoft.com/en-us/dotnet/maui/android/platform-specifics/tabbedpage-toolbar-placement?view=net-maui-9.0
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

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

public override string Issue => "[Android] Unable to set unselected iconImageSource color when toolbar placement is set to bottom";

[Test, Order(1)]
[Category(UITestCategories.TabbedPage)]
public void FontImageSourceColorShouldApplyOnBottomTabIconOnAndroid()
{
App.WaitForElement("Button");
VerifyScreenshot();
}

[Test, Order(2)]
[Category(UITestCategories.TabbedPage)]
public void DynamicFontImageSourceColorShouldApplyOnBottomTabIconOnAndroid()
{
App.WaitForElement("Button");
App.Tap("Button");
VerifyScreenshot();
}
}
}
#endif
Loading