Xamarin Forms: как изменить цвет FlyoutItem.Icon, когда он выбран или отменен?

Я использую значки шрифтов Material Design в качестве источника значков для своего проекта. Проблема в том, что, поскольку это шрифт, ему нужен другой цвет при выборе по сравнению со снятым выделением (как показано - у невыделенных белых есть белые значки, что не очень здорово).

Как я могу изменить Style, чтобы изменить цвет значка, как цвет текста и фона?

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

Редактировать 1:

Все согласны с тем, что использование VSM не сработает, потому что оно не происходит от VisualElement. Я заставил его работать с помощью Trigger, но я не доволен реализацией. Это работает:

<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>

... но, как видите, я должен установить все значение FontImageSource, которое имеет свойство Glyph, поэтому я должен повторять это Style каждый раз для каждого FlyoutItem.

Как я могу переписать это Style, чтобы его можно было использовать повторно и изменить только цвет, а не другие свойства?

Вероятно, не поддерживается. «Иконка» является собственностью FlyoutItem . Согласно описанию в диспетчере визуальных состояний, «Эта группа визуальных состояний поддерживается для всех классов, производных от VisualElement», которая не включает всплывающие элементы.

Shaw 22.12.2020 03:59

Да, я согласен. Спасибо за ссылки.

Scott Baker 22.12.2020 07:05

Material Design Font Icons может делать с Triggers то, что вы хотите. Я бы предоставил образец кода позже.

Wendy Zang - MSFT 22.12.2020 07:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
4 384
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Создайте 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>

Более подробную информацию о значках Material Design можно загрузить с GitHub. https://github.com/WendyZang/Test/tree/master/MaterialDesignIcons/App2

А затем создайте стиль, чтобы изменить цвет фона при выборе.

  <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>

Измените TextColor метки с помощью 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>

Скриншот:

Обновлено:

Изменять:

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

К:

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

Полный триггер шаблона элемента оболочки.

 <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>

Скриншот:

Вы на правильном пути, но мне нужно, чтобы он работал с цветом фона FlyoutItem.Icon. FlyoutItem не наследуется от VisualElement, как Label, поэтому вы не можете использовать VSM — вы должны использовать триггеры. Я не могу понять, как изменить ТОЛЬКО цвет фона.

Scott Baker 22.12.2020 23:50

Я обновил ответ. Если вы просто хотите изменить цвет фона, измените код в триггере для цвета фона. Я меняю цвет на желтый для вашего удобства.

Wendy Zang - MSFT 23.12.2020 07:25

Пожалуйста, смотрите последнее редактирование моего вопроса.

Scott Baker 23.12.2020 07:43

@ScottBaker Я проверил ваше редактирование. Но для цвета фона триггер используется только один раз в шаблоне данных. Не нужно повторять этот стиль каждый раз для каждого элемента FlyoutItem.

Wendy Zang - MSFT 25.12.2020 03:56

У меня был тот же вопрос, и я решил его следующим образом

Создайте пользовательское всплывающее окно с дополнительным 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); }
    }
}

Создайте FlyoutItemTemplate с двумя Lables и 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> 

Замените исходный элемент FlyoutItem в AppShell.xaml пользовательским элементом 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>

Добавьте BaseStyle в 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>

Вот результат

FlyoutItem with IconFont with different Colors for selected und deselected Item

Другие вопросы по теме