dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.02k stars 1.73k forks source link

TabBar / Tab colours not working correctly on Windows #12386

Closed samuelradford closed 1 year ago

samuelradford commented 1 year ago

Description

When trying to set the Shell.TabBarForegroundColor or Shell.TabBarUnselectedColor on a TabBar (or Tab) it does not work. In the example shown, the foreground color should be Green but it is still showing as Black and the unselected tab should be Red, but it is showing as Green.

There is no option for Selected tab.

All default styling has been removed in this example by commenting it out.

image

Steps to Reproduce

  1. Create a File > New .Net MAUI App
  2. Comment out all default styling (Resources > Styles > Styles.xaml)
  3. Create a new TabBar with 2 Tab elements in AppShell.xaml
  4. Give each Tab a Title
  5. Copy the default ShellContent into each Tab
  6. Set Shell.TabBarForegroundColor and Shell.TabBarUnselectedColor on the TabBar

Expected outcome: Foreground text color of any TabBar tabs will be the set color

Actual outcome: Foreground text color of each Tab always remains black.

Also tested by setting the property on the Tab element but still the same result.

Link to public reproduction project repository

https://github.com/samuelradford/TabBarColorTest.App

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

Windows SDK 10.0.19041.0

Did you find any workaround?

The tabs are generated from a WinUI template so if you need to workaround this before NET8 you can just replace the template here with your own template.

For example I've added this

<maui:MauiWinUIApplication.Resources>
    <DataTemplate x:Key="TabBarNavigationViewMenuItem">
        <NavigationViewItem 
    x:Name="navViewItem"
    Content="Monkey" 
    Foreground="Pink" 
    Background="Orange" 
    IsSelected="{Binding IsSelected, Mode=TwoWay}"
    MenuItemsSource="{Binding MenuItemsSource}"
    Icon="{Binding Icon}"
>
    <NavigationViewItem.Resources>
        <SolidColorBrush x:Key="TopNavigationViewItemForegroundSelected" Color="Yellow" />
        <SolidColorBrush x:Key="TopNavigationViewItemForegroundSelectedPointerOver" Color="Yellow" />
        <SolidColorBrush x:Key="TopNavigationViewItemForegroundSelectedPressed" Color="Yellow" />
        <SolidColorBrush x:Key="TopNavigationViewItemForegroundSelectedDisabled" Color="Yellow" />

        <SolidColorBrush x:Key="TopNavigationViewItemForeground" Color="Yellow" />
        <SolidColorBrush x:Key="TopNavigationViewItemForegroundPointerOver" Color="Yellow" />
        <SolidColorBrush x:Key="TopNavigationViewItemForegroundPressed" Color="Yellow" />
        <SolidColorBrush x:Key="TopNavigationViewItemForegroundDisabled" Color="Yellow" />
    </NavigationViewItem.Resources>
</NavigationViewItem>
    </DataTemplate>
</maui:MauiWinUIApplication.Resources>

Into the Platform/Windows/App.xaml file.

At this point you could use all the methods you'd use with WinUI to customize values. Generate the ControlTemplate and then modify the VisualState etc.. as needed.

You can get the ControlTemplates from here

.nuget\packages\microsoft.windowsappsdk\1.3.230502000\lib\net6.0-windows10.0.18362.0\Microsoft.WinUI\Themes

Relevant log output

No response

ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

holecekp commented 1 year ago

I have the same problem. Tabs on Windows do not look right because the Selected color cannot be set.

PureWeen commented 1 year ago

I've updated the description on this issue with a workaround for NET7

ghost commented 1 year ago

Hello lovely human, thank you for your comment on this issue. Because this issue has been closed for a period of time, please strongly consider opening a new issue linking to this issue instead to ensure better visibility of your comment. Thank you!

BenBtg commented 1 year ago

Suggested workaround does not appear to work for me on NET7. Does not affect Text colour. Only tab background. Looks like current fix in only NET8 currently. Do we have any suggested workaround that will work on NET7 for TabItem Text Color?

BenBtg commented 1 year ago

Workaround in description has been updated and I can confirm it works for me in NET7.

BenBtg commented 1 year ago

FYI Fixed confirm in .NET8. However there remains an edge case for the workaround in .NET where tab icon images are initialised to black even when foreground color is set to white. This only occurs when Windows Theme is in Light Mode.

ghost commented 1 year ago

Hello lovely human, thank you for your comment on this issue. Because this issue has been closed for a period of time, please strongly consider opening a new issue linking to this issue instead to ensure better visibility of your comment. Thank you!

mikeparker104 commented 1 year ago

FYI Fixed confirm in .NET8. However there remains an edge case for the workaround in .NET where tab icon images are initialised to black even when foreground color is set to white. This only occurs when Windows Theme is in Light Mode.

As an interim workaround, you could explore using an IValueConverter to explicitly set the Foreground of the Microsoft.UI.Xaml.Controls.BitmapIcon when the Windows Theme is in Light Mode. For example:

  1. Implement the workaround provided above and as demonstrated in the repro sample provided in #16575 - Windows TabBar Icons do not use the correct color

  2. Create an IValueConverter in the Platform/Windows folder conditionally setting the icon foreground

    internal class TabBarIconConverter : Microsoft.UI.Xaml.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value is not Microsoft.UI.Xaml.Controls.BitmapIcon bitmapIcon || 
                Microsoft.UI.Xaml.Application.Current.RequestedTheme != Microsoft.UI.Xaml.ApplicationTheme.Light)
                return value;
    
            bitmapIcon.Foreground = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.White);
    
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
            => throw new NotImplementedException();
    }
  3. Add the TabBarIconConverter to App.xaml (alongside the DataTemplate provided by the workaround above). Then, update the NavigationViewItem Icon binding to use the TabBarIconConverter

    <local:TabBarIconConverter x:Key="TabBarIconConverter" />
    
    ...
    
    <DataTemplate x:Key="TabBarNavigationViewMenuItem">
        <NavigationViewItem 
            x:Name="navViewItem" 
            ...
            Icon="{Binding Icon, Converter={StaticResource TabBarIconConverter}}">
            ...
        </NavigationViewItem>
     </DataTemplate>
    
unombun commented 1 year ago

FYI Fixed confirm in .NET8. However there remains an edge case for the workaround in .NET where tab icon images are initialised to black even when foreground color is set to white. This only occurs when Windows Theme is in Light Mode.

As an interim workaround, you could explore using an IValueConverter to explicitly set the Foreground of the Microsoft.UI.Xaml.Controls.BitmapIcon when the Windows Theme is in Light Mode. For example:

1. Implement the workaround provided above and as demonstrated in the [repro sample](https://github.com/flesarradu/WindowsTabBarColorsIssue/blob/main/Platforms/Windows/App.xaml) provided in [#16575 - Windows TabBar Icons do not use the correct color](https://github.com/dotnet/maui/issues/16575)

2. Create an `IValueConverter` in the Platform/Windows folder conditionally setting the icon foreground
   ```cs
   internal class TabBarIconConverter : Microsoft.UI.Xaml.Data.IValueConverter
   {
       public object Convert(object value, Type targetType, object parameter, string language)
       {
           if (value is not Microsoft.UI.Xaml.Controls.BitmapIcon bitmapIcon || 
               Microsoft.UI.Xaml.Application.Current.RequestedTheme != Microsoft.UI.Xaml.ApplicationTheme.Light)
               return value;

           bitmapIcon.Foreground = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.White);

           return value;
       }

       public object ConvertBack(object value, Type targetType, object parameter, string language)
           => throw new NotImplementedException();
   }
   ```

3. Add the `TabBarIconConverter` to App.xaml (alongside the `DataTemplate` provided by the workaround above). Then, update the [NavigationViewItem Icon](https://github.com/flesarradu/WindowsTabBarColorsIssue/blob/95fd4b3ef59bfbd67d4054215c58696d8b82011e/Platforms/Windows/App.xaml#L16C15-L16C15) binding to use the `TabBarIconConverter`
   ```
   <local:TabBarIconConverter x:Key="TabBarIconConverter" />

   ...

   <DataTemplate x:Key="TabBarNavigationViewMenuItem">
       <NavigationViewItem 
           x:Name="navViewItem" 
           ...
           Icon="{Binding Icon, Converter={StaticResource TabBarIconConverter}}">
           ...
       </NavigationViewItem>
    </DataTemplate>
   ```

I confirm that this workaround works