Skip to content

Commit ca2c248

Browse files
authored
[Android] Fix for the FontImageSource color is not applied properly to the Bottom Tab Icon (#29317)
* Fixed the FontImageSource Icon color issues on the BottomNavigationView Tabs * Committed the test sample and case * Added comment over the fix * Remove unnecessary space
1 parent 6492696 commit ca2c248

File tree

5 files changed

+193
-3
lines changed

5 files changed

+193
-3
lines changed

src/Controls/src/Core/Platform/Android/TabbedPageManager.cs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
438438
{
439439
menuItem.SetIcon(result.Value);
440440
});
441+
SetupBottomNavigationViewIconColor(page, menuItem, index);
441442
}
442443
else
443444
{
@@ -652,8 +653,13 @@ int GetItemTextColor(Color customColor, ColorStateList originalColors)
652653
return customColor?.ToPlatform().ToArgb() ?? originalColors?.DefaultColor ?? 0;
653654
}
654655

655-
protected virtual ColorStateList GetItemIconTintColorState()
656+
protected virtual ColorStateList GetItemIconTintColorState(Page page)
656657
{
658+
if (page.IconImageSource is FontImageSource fontImageSource && fontImageSource.Color is not null)
659+
{
660+
return null;
661+
}
662+
657663
if (_orignalTabIconColors is null)
658664
{
659665
_orignalTabIconColors = IsBottomTabPlacement ? _bottomNavigationView.ItemIconTintList : _tabLayout.TabIconTint;
@@ -773,7 +779,14 @@ void UpdateItemIconColor()
773779
_newTabIconColors = null;
774780

775781
if (IsBottomTabPlacement)
776-
_bottomNavigationView.ItemIconTintList = GetItemIconTintColorState() ?? _orignalTabIconColors;
782+
{
783+
for (int i = 0; i < _bottomNavigationView.Menu.Size(); i++)
784+
{
785+
var menuItem = _bottomNavigationView.Menu.GetItem(i);
786+
var page = Element.Children[i];
787+
SetupBottomNavigationViewIconColor(page, menuItem, i);
788+
}
789+
}
777790
else
778791
{
779792
for (int i = 0; i < _tabLayout.TabCount; i++)
@@ -785,6 +798,28 @@ void UpdateItemIconColor()
785798
}
786799
}
787800

801+
void SetupBottomNavigationViewIconColor(Page page, IMenuItem menuItem, int i)
802+
{
803+
// Updating the icon color of each BottomNavigationView item individually works correctly.
804+
// This is necessary because `ItemIconTintList` applies the color globally to all items,
805+
// which doesn't allow for per-item customization.
806+
// Currently, there is no modern API that provides the desired behavior.
807+
// Therefore, the obsolete `BottomNavigationItemView` approach is used.
808+
#pragma warning disable XAOBS001 // Type or member is obsolete
809+
if (_bottomNavigationView.GetChildAt(0) is BottomNavigationMenuView menuView)
810+
{
811+
var itemView = menuView.GetChildAt(i) as BottomNavigationItemView;
812+
813+
if (itemView != null && itemView.Id == menuItem.ItemId)
814+
{
815+
ColorStateList colors = GetItemIconTintColorState(page);
816+
817+
itemView.SetIconTintList(colors);
818+
}
819+
}
820+
#pragma warning restore XAOBS001 // Type or member is obsolete
821+
}
822+
788823
internal void UpdateTabItemStyle()
789824
{
790825
Color barItemColor = BarItemColor;
@@ -830,7 +865,7 @@ void SetIconColorFilter(Page page, TabLayout.Tab tab, bool selected)
830865
if (icon == null)
831866
return;
832867

833-
ColorStateList colors = (page.IconImageSource is FontImageSource fontImageSource && fontImageSource.Color is not null) ? null : GetItemIconTintColorState();
868+
ColorStateList colors = GetItemIconTintColorState(page);
834869
if (colors == null)
835870
ADrawableCompat.SetTintList(icon, null);
836871
else
27.4 KB
Loading
27.4 KB
Loading
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;
2+
using Button = Microsoft.Maui.Controls.Button;
3+
4+
namespace Maui.Controls.Sample.Issues;
5+
6+
[Issue(IssueTracker.Github, 29109, "[Android] Unable to set unselected iconImageSource color when toolbar placement is set to bottom", PlatformAffected.Android)]
7+
public class Issue29109 : TestTabbedPage
8+
{
9+
protected override void Init()
10+
{
11+
// Set the toolbar placement to bottom (android specific)
12+
On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().SetToolbarPlacement(Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.ToolbarPlacement.Bottom);
13+
// Set tab colors
14+
this.SelectedTabColor = Colors.Red;
15+
this.UnselectedTabColor = Colors.Gray;
16+
17+
// Add tabs
18+
this.Children.Add(new Issue29109Tab1());
19+
this.Children.Add(new Issue29109Tab2());
20+
this.Children.Add(new Issue29109Tab3());
21+
}
22+
}
23+
24+
public class Issue29109Tab1 : ContentPage
25+
{
26+
public Issue29109Tab1()
27+
{
28+
//If no FontImageSource color is given, tab icon should be applied based on the SelectedTabColor and UnselectedTabColor.
29+
IconImageSource = new FontImageSource
30+
{
31+
FontFamily = "Ion",
32+
Glyph = "\uf47e",
33+
Size = 15
34+
};
35+
Button button = new Button
36+
{
37+
Text = "Change Tab Icon Color",
38+
BackgroundColor = Colors.Green,
39+
TextColor = Colors.White
40+
};
41+
button.AutomationId = "Button";
42+
button.Clicked += (s, e) =>
43+
{
44+
//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.
45+
(this.IconImageSource as FontImageSource).Color = Colors.Orange;
46+
};
47+
Title = "Tab 1";
48+
var verticalStackLayout = new VerticalStackLayout
49+
{
50+
VerticalOptions = LayoutOptions.Center,
51+
Children = {
52+
new Label
53+
{
54+
HorizontalOptions = LayoutOptions.Center,
55+
Text = "Tab 1"
56+
},
57+
button
58+
}
59+
60+
};
61+
Content = verticalStackLayout;
62+
}
63+
}
64+
65+
public class Issue29109Tab2 : ContentPage
66+
{
67+
public Issue29109Tab2()
68+
{
69+
//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.
70+
IconImageSource = new FontImageSource
71+
{
72+
FontFamily = "Ion",
73+
Glyph = "\uf47e",
74+
Color = Colors.DodgerBlue,
75+
Size = 15
76+
};
77+
78+
Title = "Tab 2";
79+
var verticalStackLayout = new VerticalStackLayout
80+
{
81+
VerticalOptions = LayoutOptions.Center,
82+
Children =
83+
{
84+
new Label
85+
{
86+
HorizontalOptions = LayoutOptions.Center,
87+
Text = "Tab 2"
88+
},
89+
}
90+
};
91+
Content = verticalStackLayout;
92+
}
93+
}
94+
public class Issue29109Tab3 : ContentPage
95+
{
96+
public Issue29109Tab3()
97+
{
98+
//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.
99+
IconImageSource = new FontImageSource
100+
{
101+
FontFamily = "Ion",
102+
Glyph = "\uf47e",
103+
Color = Colors.Green,
104+
Size = 15
105+
};
106+
107+
Title = "Tab 3";
108+
var verticalStackLayout = new VerticalStackLayout
109+
{
110+
VerticalOptions = LayoutOptions.Center,
111+
Children =
112+
{
113+
new Label
114+
{
115+
HorizontalOptions = LayoutOptions.Center,
116+
Text = "Tab 3"
117+
},
118+
}
119+
};
120+
Content = verticalStackLayout;
121+
}
122+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#if ANDROID
2+
//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
3+
using NUnit.Framework;
4+
using UITest.Appium;
5+
using UITest.Core;
6+
7+
namespace Microsoft.Maui.TestCases.Tests.Issues
8+
{
9+
public class Issue29109 : _IssuesUITest
10+
{
11+
public Issue29109(TestDevice device) : base(device) { }
12+
13+
public override string Issue => "[Android] Unable to set unselected iconImageSource color when toolbar placement is set to bottom";
14+
15+
[Test, Order(1)]
16+
[Category(UITestCategories.TabbedPage)]
17+
public void FontImageSourceColorShouldApplyOnBottomTabIconOnAndroid()
18+
{
19+
App.WaitForElement("Button");
20+
VerifyScreenshot();
21+
}
22+
23+
[Test, Order(2)]
24+
[Category(UITestCategories.TabbedPage)]
25+
public void DynamicFontImageSourceColorShouldApplyOnBottomTabIconOnAndroid()
26+
{
27+
App.WaitForElement("Button");
28+
App.Tap("Button");
29+
VerifyScreenshot();
30+
}
31+
}
32+
}
33+
#endif

0 commit comments

Comments
 (0)