2

I am using Material Design Font Icons as my icon source for my project. The trouble is, since it's a font it needs a different color when selected vs. when deselected (as shown - the deselected white ones have white icons, which isn't awesome).

Deselected icons are the same color as the background

How can I modify the Style to change the color of the icon like it does the text and background color?

<!-- redacted because it would've never worked -->

Edit 1:

Consensus is that using the VSM isn't going to work because it doesn't derive from VisualElement. I've gotten it to work using a Trigger - but I'm not happy with the implementation. This works:

<Shell.Resources>
<ResourceDictionary>
<Style TargetType="FlyoutItem" BasedOn="{StaticResource BaseStyle}">
    <Style.Triggers>
        <Trigger TargetType="FlyoutItem" Property="IsChecked" Value="True">
            <Setter Property="Title" Value="Checked" />
            <Setter Property="FlyoutIcon" >
                <Setter.Value>
                    <FontImageSource FontFamily="MaterialDesignIconFont"
                                        Glyph="{StaticResource InformationOutlineGlyph}"
                                        Color="White" />
                </Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>

</ResourceDictionary>
</Shell.Resources>

    
<FlyoutItem Title="About" >
    <FlyoutItem.Icon>
        <FontImageSource FontFamily="MaterialDesignIconFont"
                            Glyph="{StaticResource InformationOutlineGlyph}"
                            Color="Green" />
    </FlyoutItem.Icon>

    <ShellContent Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
</FlyoutItem>

... but as you can see, I have to set the entire FontImageSource value - which has the Glyph property - so I have to repeat this Style each time for each FlyoutItem.

How can I rewrite this Style to be reusable and only change the color, not the other properties?

Scott Baker
  • 10,013
  • 17
  • 56
  • 102
  • Probably not supported. "Icon" is a property of [FlyoutItem](https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.flyoutitem?view=xamarin-forms). Based on [description in visual-state-manager](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/visual-state-manager), "This visual state group is supported for all classes that derive from VisualElement", which not includes flyout items. – Shaw Dec 22 '20 at 02:59
  • Yep, I agree. Thanks for the links. – Scott Baker Dec 22 '20 at 06:05
  • The `Material Design Font Icons` could do what you want with the `Triggers`. I would provide the code sample later. – Wendy Zang - MSFT Dec 22 '20 at 06:23

2 Answers2

4

I had the same question and solved it as follows

Create a custom flyout with an additional IconGlyphProperty

class FlyoutItemIconFont : FlyoutItem
{
    public static readonly BindableProperty IconGlyphProperty = BindableProperty.Create(nameof(IconGlyphProperty), typeof(string), typeof(FlyoutItemIconFont), string.Empty);
    public string IconGlyph
    {
        get { return (string)GetValue(IconGlyphProperty); }
        set { SetValue(IconGlyphProperty, value); }
    }
}

Create a FlyoutItemTemplate with two Lables and VisualStateManager

<Shell.ItemTemplate>
    <DataTemplate>
        <Grid>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="White" />
                                <Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="{StaticResource Primary}" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Selected">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="{StaticResource Primary}" />
                                <Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="White" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </VisualStateManager.VisualStateGroups>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.2*" />
                <ColumnDefinition Width="0.8*" />
            </Grid.ColumnDefinitions>
            <Label x:Name="FlyoutItemIcon"
                FontFamily="MaterialDesignFont"       
                Text="{Binding IconGlyph}"
                TextColor="{Binding Source={x:Reference FlyoutItemLabel} ,Path=TextColor}"
                FontSize="30"
                Margin="5"/>
            <Label x:Name="FlyoutItemLabel"
                Grid.Column="1"        
                Text="{Binding Title}"
                VerticalTextAlignment="Center" />
        </Grid>
    </DataTemplate>
</Shell.ItemTemplate> 

Replace the original FlyoutItem in AppShell.xaml with the custom FlyoutItem

<controls:FlyoutItemIconFont Title="About" IconGlyph="{StaticResource IconInfo}">
    <ShellContent Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
</controls:FlyoutItemIconFont>

<controls:FlyoutItemIconFont Title="Browse" IconGlyph="{StaticResource IconListBulleted}">
    <ShellContent Route="ItemsPage" ContentTemplate="{DataTemplate local:ItemsPage}" />
</controls:FlyoutItemIconFont>

Add the BaseStyle to the customFlyouItem

<Shell.Resources>
    <ResourceDictionary>
        <x:String x:Key="IconInfo">&#xF02FD;</x:String>
        <x:String x:Key="IconListBulleted">&#xF0279;</x:String>
        ...
        <Style TargetType="controls:FlyoutItemIconFont" BasedOn="{StaticResource BaseStyle}"/>
    </ResourceDictionary>
</Shell.Resources>

Here is the Result

FlyoutItem with IconFont with different Colors for selected und deselected Item

Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58
CarstenD
  • 41
  • 2
2

Create the Material Design Icons.

 <Application.Resources>
    <ResourceDictionary>
        <Color x:Key="fgColor">#66169C</Color>
        <Color x:Key="bgColor">#FFFFFF</Color>
        <Color x:Key="OverDueItem">#FF1C07</Color>

        <OnPlatform x:Key="Material" x:TypeArguments="x:String">
            <On Platform="iOS" Value="Material Design Icons" />
            <On Platform="Android" Value="materialdesignicons-webfont.ttf#Material Design Icons" />
        </OnPlatform>

        <Style x:Key="MaterialIcons" TargetType="{x:Type Label}">
            <Setter Property="FontFamily" Value="{DynamicResource Material}" />
            <Setter Property="FontSize" Value="100" />
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="TextColor" Value="{DynamicResource fgColor}" />
            <Setter Property="FontSize" Value="Large" />
        </Style>
    </ResourceDictionary>
</Application.Resources>

For more details about the Material Design Icons, you could download from the GitHub. https://github.com/WendyZang/Test/tree/master/MaterialDesignIcons/App2

And then create the style to change the background color when you selected.

  <Style x:Key="FloutItemStyle" TargetType="Grid">
        <Setter Property="VisualStateManager.VisualStateGroups">
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="Selected">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor" Value="Accent" />

                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </Setter>
    </Style>

Change the Label TextColor with the Triggers.

 <Shell.ItemTemplate>
    <DataTemplate>
        <Grid x:Name="grid" Style="{StaticResource FloutItemStyle}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.2*" />
                <ColumnDefinition Width="0.8*" />

            </Grid.ColumnDefinitions>
           
            <Label Style="{StaticResource MaterialIcons}" Text="&#xf001;">
                <Label.Triggers>
                    <DataTrigger
                        Binding="{Binding Source={x:Reference grid}, Path=BackgroundColor}"
                        TargetType="Label"
                        Value="Accent">
                        <Setter Property="TextColor" Value="White" />
                    </DataTrigger>
                </Label.Triggers>
            </Label>
            <Label
                Grid.Column="1"
                FontAttributes="Italic"
                Text="{Binding Title}"
                VerticalTextAlignment="Center">
                <Label.Triggers>
                    <DataTrigger
                        Binding="{Binding Source={x:Reference grid}, Path=BackgroundColor}"
                        TargetType="Label"
                        Value="Accent">
                        <Setter Property="TextColor" Value="White" />
                    </DataTrigger>
                </Label.Triggers>
            </Label>
        </Grid>
    </DataTemplate>
</Shell.ItemTemplate>

Screenshot:

enter image description here

Updated:

Change:

<Setter Property="TextColor" Value="White" />

To:

 <Setter Property="BackgroundColor" Value="Yellow" />

The whold trigger of the shell itemtemplate.

 <Label.Triggers>
                    <DataTrigger
                        Binding="{Binding Source={x:Reference grid}, Path=BackgroundColor}"
                        TargetType="Label"
                        Value="Accent">
                        <!--<Setter Property="TextColor" Value="White" />-->
                        <Setter Property="BackgroundColor" Value="Yellow" />
                    </DataTrigger>
                </Label.Triggers>

Screenshot:

enter image description here

Wendy Zang - MSFT
  • 10,509
  • 1
  • 7
  • 17
  • 1
    You're on the right track, but I need it to work with `FlyoutItem.Icon` background color. `FlyoutItem` doesn't inherit from `VisualElement` like a `Label` - so you can't use VSM - you have to use triggers. I can't figure out how to change JUST the background color. – Scott Baker Dec 22 '20 at 22:50
  • I have updated the reply. If you just want to change the background color, change the code in trigger for the background color. I change the color to yellow for your reference. – Wendy Zang - MSFT Dec 23 '20 at 06:25
  • Please see the latest edit to my question. – Scott Baker Dec 23 '20 at 06:43
  • 1
    @ScottBaker I have checked you edit. But for the background color, the trigger only used once in datatemplate. Do not need to repeat this Style each time for each FlyoutItem. – Wendy Zang - MSFT Dec 25 '20 at 02:56