xamlxamarinxamarin.formsapp.xamlapp-shell

Xamarin Forms: How Can I Change the FlyoutItem.Icon's Color When It Is Selected/Deselected?


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?


Solution

  • 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