0

I am implementing a Xamarin.Forms app using AppShell and can't seem to figure out how to set the color of the selected / unselected icons in the Flyout menu. Here is the section of the appshell.xaml that I believe is controlling the behavior (I used various high contrast colors to show what settings are controlling what). (The complete code sample: https://github.com/wadebaird/ShellExample for more reference):

<Style x:Name="FlyoutItem" Class="FlyoutItemLayoutStyle" TargetType="Layout" ApplyToDerivedTypes="True">
        <Setter Property="VisualStateManager.VisualStateGroups">
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal">
                        <VisualState.Setters>
                            <!-- This is the color of the unselected text for the labels in the flyout-->
                            <Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="Magenta" />
                            <Setter TargetName="FlyoutItemLabel" Property="Label.BackgroundColor" Value="Cyan" />
                            <!-- This is the background color of the selected icon in the flyout -->
                            <Setter Property="BackgroundColor" Value="Green" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Selected">
                        <VisualState.Setters>
                            <!-- This is the color of the selected text in the flyout -->
                            <Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="Black"/>
                            <Setter TargetName="FlyoutItemLabel" Property="Label.BackgroundColor" Value="Yellow" />
                            <!-- This is the background color of the selected icon in the flyout -->
                            <Setter Property="BackgroundColor" Value="Red" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </Setter>
    </Style>

And here is the visuals from these settings. In this image, the "Entity at the top is the "selected" item. I would expect / want the icons to match the colors of the text but can't seem to find the setting.

enter image description here

Here is what I'm going for to show how "white" for the icons doesn't work:

enter image description here

I can manually set the color on the FontImageSource, but then it is always that color and doesn't match the selected / unselected:

<ShellContent Route="aboutPage" Title="About" ContentTemplate="{DataTemplate views:AboutPage}" >
    <ShellContent.Icon>
        <FontImageSource Size="{StaticResource FlyoutIconSize}" Color="Black" Glyph="{x:Static fontAwesome:FontAwesomeIcons.InfoCircle}" FontFamily="FA-Solid" />
    </ShellContent.Icon>
</ShellContent>

I tried various things such as this withing the "Common States"- "Normal"/"Selected" and couldn't get anything to work.:

<Setter Property="FontImageSource.Color" Value="{AppThemeBinding Light={StaticResource PrimaryUnselectedTextColorLight}, Dark={StaticResource PrimaryUnselectedTextColorDark}}" />

And on a side note (and this is probably a bug). It appears on iOS that when first opening the flyout nothing is "selected":

enter image description here

Where on Android, the proper item is selected:

enter image description here

I know this is a seperate item, and I'll log a bug if I can't find an existing issue/bug, but I figured I'd mention it as someone thgat knows the answer to my above probably is already aware of this issue.

Wade Baird
  • 194
  • 1
  • 16

2 Answers2

0

You could use the Shell.ItemTemplate to set the background color of the Label and Icon. And use the VisualStateGroup to change the color of Selected status.

Shell.ItemTemplate:

   <Shell.ItemTemplate>
    <DataTemplate>
        <Grid ColumnDefinitions="0.2*,0.8*" ColumnSpacing="0" Style="{StaticResource FloutItemStyle}">
            <Image  x:Name="FlyoutItemIcon"  Source="{Binding FlyoutIcon}" HeightRequest="45" />
            <Label x:Name="FlyoutItemLabel"   Grid.Column="1"
                   Text="{Binding Title}"
                   FontAttributes="Italic"
                   VerticalTextAlignment="Center" />
        </Grid>
    </DataTemplate>
</Shell.ItemTemplate>

Style:

 <Style  x:Key="FloutItemStyle" Class="FlyoutItemLayoutStyle" TargetType="Layout" ApplyToDerivedTypes="True">
            <Setter Property="VisualStateManager.VisualStateGroups">
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="{x:OnPlatform UWP=Transparent, iOS=White}" />
                                <Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="{StaticResource Primary}" />
                                <Setter TargetName="FlyoutItemLabel" Property="Label.BackgroundColor" Value="Blue" />
                                <Setter TargetName="FlyoutItemIcon" Property="Image.BackgroundColor" Value="Green" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Selected">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="{StaticResource Primary}" />
                                <Setter TargetName="FlyoutItemLabel" Property="Label.BackgroundColor" Value="{StaticResource Primary}" />
                                <Setter TargetName="FlyoutItemIcon" Property="Image.BackgroundColor" Value="{StaticResource Primary}" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </Setter>
        </Style>

enter image description here

Wendy Zang - MSFT
  • 10,509
  • 1
  • 7
  • 17
  • Thank you for taking the time to answer. However, I need to control the color of the icon, not the background (the background is correct). I don't see a setting on Image for the color of the image. And I am using a Font Icon, not an image too. Thanks! – Wade Baird Feb 24 '22 at 15:15
0

After Wendy Zang replied with a partial solution (it solved the background color but not the foreground), it got me on the right track and I was able to find the answer to this posted question, which utilized two labels instead of an image. (I also tried to use the Image that Wendy suggested above and an effect like the IconTintColorEffect.TintColor from this post, but I couldn't get that to work quite right either as the sizing of the icon was a lot trickier with it being an image.)

I tried the solution with having the different types of derived classes with the IconGlyph property and I got it to work well, but I didn't like the cleanliness of it. I then thought of using an IValueConverter to fix the binding for the label class:

public class FlyoutGlyphConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return null;

        if (value is not BaseShellItem baseShellItem)
            throw new ArgumentException($"This converter may only be used on values of type {nameof(BaseShellItem)}.");

        if (baseShellItem.Icon is not FontImageSource fontImageSource)
            throw new ArgumentException($"This converter may only be used on values of type {nameof(BaseShellItem)}s with Icons of type {nameof(FontImageSource)}.");

        return fontImageSource.Glyph;
    }
}

And my xaml ended up being like so:

<Shell.ItemTemplate>
    <DataTemplate x:DataType="root:IShellIconFont">
        <Grid Margin="0" Padding="0" ColumnSpacing="0">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal">
                            <VisualState.Setters>
                                <!-- This is the color of the unselected text for the labels in the flyout-->
                                <Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="#2196F3" />
                                <Setter TargetName="FlyoutItemLabel" Property="Label.BackgroundColor" Value="White" />
                                <!-- This is the background color of the selected icon in the flyout -->
                                <Setter TargetName="FlyoutItemIcon" Property="Image.BackgroundColor" Value="White" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Selected">
                            <VisualState.Setters>
                                <!-- This is the color of the selected text in the flyout -->
                                <Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="White"/>
                                <Setter TargetName="FlyoutItemLabel" Property="Label.BackgroundColor" Value="#2196F3" />
                                <!-- This is the background color of the selected icon in the flyout -->
                                <Setter TargetName="FlyoutItemIcon" Property="Image.BackgroundColor" Value="#2196F3" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </VisualStateManager.VisualStateGroups>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.2*" />
                <ColumnDefinition Width="0.8*" />
            </Grid.ColumnDefinitions>
            <Label x:Name="FlyoutItemIcon" Grid.Column="0" FontFamily="FA-Solid" FontSize="{StaticResource FlyoutIconSize}"
                    Text="{Binding ., Converter={StaticResource FlyoutGlyph}}" TextColor="{Binding Source={x:Reference FlyoutItemLabel}, Path=TextColor}"
                    VerticalTextAlignment="Center" HorizontalTextAlignment="Center"
                    Margin="0" Padding="0"/>
            <Label x:Name="FlyoutItemLabel" Grid.Column="1" Text="{Binding Title}" FontSize="{StaticResource FlyoutLabelFontSize}" 
                    FontAttributes="Bold" VerticalTextAlignment="Center" HeightRequest="45" />
        </Grid>
    </DataTemplate>
</Shell.ItemTemplate>
<FlyoutItem Route="root" Title="Entitys" FlyoutDisplayOptions="AsMultipleItems">
    <root:ShellContentIconFont Route="mainPage" Title="Entity" Glyph="{x:Static fontAwesome:FontAwesomeIcons.BookOpen}" ContentTemplate="{DataTemplate views:MainPage}" />
    <root:ShellContentIconFont Route="favoritesPage" Title="Favorites" Glyph="{x:Static fontAwesome:FontAwesomeIcons.Star}" ContentTemplate="{DataTemplate views:FavoritesPage}" />
    <root:TabIconFont Route="entitys" Title="Entitys" Glyph="{x:Static fontAwesome:FontAwesomeIcons.Book}" >
        <ShellContent Route="entitysCalendar" Title="Calendar" ContentTemplate="{DataTemplate views:EntitysCalendarPage}" />
        <ShellContent Route="entitysList" Title="List" ContentTemplate="{DataTemplate views:EntitysListPage}" />
    </root:TabIconFont>
</FlyoutItem>
<FlyoutItem Route="root" Title="Entitys" FlyoutDisplayOptions="AsMultipleItems">
    <ShellContent Route="mainPage" Title="Entity" ContentTemplate="{DataTemplate views:MainPage}">
        <ShellContent.Icon>
            <FontImageSource Size="{StaticResource FlyoutIconSize}" Glyph="{x:Static fontAwesome:FontAwesomeIcons.BookOpen}" FontFamily="FA-Solid" />
        </ShellContent.Icon>
    </ShellContent>
    <ShellContent Route="favoritesPage" Title="Favorites" ContentTemplate="{DataTemplate views:FavoritesPage}">
        <ShellContent.Icon>
            <FontImageSource Size="{StaticResource FlyoutIconSize}" Glyph="{x:Static fontAwesome:FontAwesomeIcons.Star}" FontFamily="FA-Solid" />
        </ShellContent.Icon>
    </ShellContent>
    <Tab Route="entitys" Title="Entitys">
        <Tab.Icon>
            <FontImageSource Size="{StaticResource FlyoutIconSize}" Glyph="{x:Static fontAwesome:FontAwesomeIcons.Book}" FontFamily="FA-Solid" />
        </Tab.Icon>
        <ShellContent Route="entitysCalendar" Title="Calendar" ContentTemplate="{DataTemplate views:EntitysCalendarPage}" />
        <ShellContent Route="entitysList" Title="List" ContentTemplate="{DataTemplate views:EntitysListPage}" />
    </Tab>
</FlyoutItem>
<ShellContent Route="aboutPage" Title="About" ContentTemplate="{DataTemplate views:AboutPage}" >
    <ShellContent.Icon>
        <FontImageSource Size="{StaticResource FlyoutIconSize}" Glyph="{x:Static fontAwesome:FontAwesomeIcons.InfoCircle}" FontFamily="FA-Solid" />
    </ShellContent.Icon>
</ShellContent>

Here is the final result:

enter image description here

A side not, something in this solution fixed the iOS issue where nothing was selected on initial opening. I'm guessing it was the definded DataTemplate.

Wade Baird
  • 194
  • 1
  • 16