Xamarin 列表视图选定项目更改图标颜色

Posted

技术标签:

【中文标题】Xamarin 列表视图选定项目更改图标颜色【英文标题】:Xamarin List View Selected Item Change Icon Color 【发布时间】:2021-02-05 10:49:45 【问题描述】:

我已将滑块菜单实现为 ​​ListView,并且可以轻松地将颜色分配给菜单中的任何图标。但是,我正在尝试更改所选 ListView 行的颜色(特别是图标)。我试过使用转换器,但值永远不会改变。

这是我的 xaml:

<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         mc:Ignorable="d"
         x:Class="SycretBeauty.Screens.MainMenuMaster"
         Title="Master"
         xmlns:controls="clr-namespace:SycretBeauty;assembly=SycretBeauty"
         xmlns:converters="clr-namespace:SycretBeauty.Converters;assembly=SycretBeauty"
         BackgroundColor="StaticResource color_menu_item_background"
         IconImageSource="images/menu.png">

    <StackLayout
    BackgroundColor="StaticResource color_header_banner_background">

        <Image
            VerticalOptions="Center"
            HorizontalOptions="FillAndExpand"
            Source="images/bannerVialang.png"
            Margin="0,30,0,20">
        </Image>

        <controls:SuperListView
            x:Name="MenuItemsListView"
            SeparatorVisibility="Default"
            HasUnevenRows="False"
            Margin="0,0,0,0"
            RowHeight="120"
            IsScrollingEnable="False"
            SelectedItem="Binding SelectedItem"
            ItemsSource="Binding MenuItems"
            BackgroundColor="StaticResource color_menu_item_background">

        <d:ListView.ItemsSource>
            <x:Array Type="x:Type x:String">
                <x:String>Записаться</x:String>
                <x:String>Акции</x:String>
                <x:String>Уведомления</x:String>
                <x:String>Личный кабинет</x:String>
                <x:String>Контакты</x:String>
                <x:String>Отзывы</x:String>
                <x:String>Галерея</x:String>
                <x:String>Поделиться</x:String>
            </x:Array>
        </d:ListView.ItemsSource>

        <controls:SuperListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Grid
                        VerticalOptions="FillAndExpand"
                        ColumnSpacing="0">

                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="60"/>
                            <ColumnDefinition Width="10"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <StackLayout
                            Grid.Column="0"
                            BackgroundColor="StaticResource color_menu_item_background"
                            VerticalOptions="FillAndExpand"
                            HorizontalOptions="FillAndExpand">

                             <controls:IconView
                                VerticalOptions="CenterAndExpand"
                                HeightRequest="35"
                                Foreground="Binding ForegroundColor"
                                Source="Binding ImgSource">
                             </controls:IconView>             
                        </StackLayout>
            
                        <Label
                            Grid.Column="0"
                            Text="Binding PushCount" 
                            IsVisible="Binding PushUnread"
                            d:Text="23"
                            d:IsVisible="True"
                            HorizontalOptions="FillAndExpand"
                            VerticalOptions="FillAndExpand"
                            HorizontalTextAlignment="Center"
                            VerticalTextAlignment="Center"
                            TextColor="White"/>
            
                        <StackLayout Grid.Column="1"
                            BackgroundColor="StaticResource color_menu_item_background"
                            VerticalOptions="CenterAndExpand"
                            HorizontalOptions="FillAndExpand">
                        </StackLayout>

                        <Label Grid.Column="2"
                            BackgroundColor="StaticResource color_menu_item_background"
                            VerticalOptions="FillAndExpand" 
                            VerticalTextAlignment="Center" 
                            Text="Binding Title" 
                            d:Text="Binding ."
                            Style="StaticResource font_menu_item_text"/>
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </controls:SuperListView.ItemTemplate>
    </controls:SuperListView>
</StackLayout>

这是模型:

    public class MainMenuItem

    public MainMenuItem()
    
        TargetType = typeof(MainMenuItem);
    
    public int Id  get; set; 
    public string ImgSource  get; set; 
    public string Title  get; set; 
    public Type TargetType  get; set; 
    public Action ItemSelected  get; set; 
    public string PushCount  get; set; 
    public bool PushUnread  get; set; 
    public Color ForegroundColor  get; set; 

这里是cs:

public partial class MainMenuMaster : ContentPage

    public ListView ListView;
    public AppContext Context  get; set; 

    private float rowHeight;

    public MainMenuMaster()
    
        InitializeComponent();
        BindingContext = new ViewModel();
        ListView = MenuItemsListView;
        ListView.SizeChanged += ListView_SizeChanged;
    


    private void ListView_SizeChanged(object sender, EventArgs e)
    
        var h = ListView.Height;
        rowHeight = (float)(h / 8);
        ListView.RowHeight = (int)rowHeight;
    

    protected override void OnAppearing()
    
        base.OnAppearing();
        (BindingContext as ViewModel).UpdatePushCount(Context.UnreadPushCount);
    

    public class ViewModel : INotifyPropertyChanged
     
        public ObservableCollection<MainMenuItem> MenuItems  get; set; 
        public AppContext Context  get; set; 
        public ViewModel()
        
            MenuItems = new ObservableCollection<MainMenuItem>(new[]
            
                new MainMenuItem 
                    Id = 0,
                    ImgSource = "images/signup.png",
                    Title = "Записаться",
                    TargetType = typeof(OnlineSignupScreen),
                    ItemSelected = () => 
                        Context.SelectSalonStart(typeof(OnlineSignupScreen));
                    ,
                    ForegroundColor = Color.Gray
                ,
                new MainMenuItem 
                    Id = 1,
                    ImgSource = "images/promos",
                    Title = "Акции",
                    TargetType = typeof(PromosScreen),
                    ForegroundColor = Color.Gray,
                ,
                new MainMenuItem 
                    Id = 2,
                    ImgSource = "images/notify",
                    Title = "Уведомления",
                    TargetType = typeof(NotificationsScreen),
                    ForegroundColor = Color.Gray
                ,
                new MainMenuItem 
                    Id = 3,
                    ImgSource = "images/personal",
                    Title = "Личный кабинет",
                    TargetType = typeof(PersonalInfoScreen),
                    ForegroundColor = Color.Gray
                ,
                new MainMenuItem 
                    Id = 4,
                    ImgSource = "images/contacts",
                    Title = "Контакты",
                    TargetType = typeof(ContactsScreen),
                    ItemSelected = () => 
                        Context.SelectSalonStart(typeof(ContactsScreen));
                    ,
                    ForegroundColor = Color.Gray
                ,
                new MainMenuItem 
                    Id = 5,
                    ImgSource = "images/feedback.png",
                    Title = "Отзывы",
                    TargetType = typeof(FeedbackScreen),
                    ItemSelected = () => 
                        Context.SelectSalonStart(typeof(FeedbackScreen));
                    ,
                    ForegroundColor = Color.Gray
                ,
                new MainMenuItem 
                    Id = 6,
                    ImgSource = "images/gallery.png",
                    Title = "Галерея",
                    TargetType = typeof(GalleryScreen),
                    ItemSelected = () => 
                        Context.SelectSalonStart(typeof(GalleryScreen));
                    ,
                    ForegroundColor = Color.Gray
                ,
                new MainMenuItem 
                    Id = 7,
                    ImgSource = "images/share",
                    Title = "Поделиться",
                    TargetType = typeof(ShareWithFriendScreen),
                    ForegroundColor = Color.Gray
                
            );

        

        public void UpdatePushCount(int count)
        
            MenuItems[2].ImgSource = count > 0 ? "images/badge" : "images/notify";
            MenuItems[2].PushCount = count.ToString();
            MenuItems[2].PushUnread = count > 0;
        

        #region INotifyPropertyChanged Implementation
        public event PropertyChangedEventHandler PropertyChanged;
        void OnPropertyChanged([CallerMemberName] string propertyName = "")
        
            if (PropertyChanged == null)
                return;

            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        
        #endregion
    

我还有控制导航的 MainMenu 和 ListView_onSelected 方法,但即使在那里我也无法更改图标的颜色。

【问题讨论】:

【参考方案1】:

请为MainMenuItem.cs实现INotifyPropertyChanged接口

然后像下面的代码一样更改 ForegroundColor 属性。

 public class MainMenuItem: INotifyPropertyChanged
    
        public MainMenuItem()
        
            TargetType = typeof(MainMenuItem);
        
        public int Id  get; set; 
        public string ImgSource  get; set; 
        public string Title  get; set; 
        public Type TargetType  get; set; 
        public Action ItemSelected  get; set; 
        public string PushCount  get; set; 
        public bool PushUnread  get; set; 
      


        private Color _foregroundColor;

        public Color ForegroundColor
        
            get  return _foregroundColor; 
            set
            
                _foregroundColor = value;

                OnPropertyChanged("ForegroundColor");

            
        

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        
    

我不知道controls:SuperListViewcontrols:IconView的成就是什么,我用listviewImageButton替换它,如果项目被选中。我们可以更改ImageButton的背景颜色进行测试。

  <ImageButton
           Source="Binding ImgSource"
           VerticalOptions="CenterAndExpand"
           HeightRequest="35"
           BackgroundColor="Binding ForegroundColor"
           >
  </ImageButton>

 private void MenuItemsListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        
            // MainMenuItem mainMenuItem = sender as MainMenuItem;

            MainMenuItem mainMenuItem = viewModel.MenuItems[e.SelectedItemIndex];
            mainMenuItem.ForegroundColor = Color.Red;
        

这里正在运行 GIF。

【讨论】:

我可以通过在列表视图的onSelected 方法中设置var item = e.selectedItemitem.ForegroundColor = color 来设置项目的颜色。但是,当我在列表视图中选择其他元素时,颜色会停留在先前选择的行上。更改所选菜单项时如何“取消选择”其他元素? 您可以在模型中添加IsSelect属性(请实现ForegroundColor这样的格式)。执行MenuItemsListView_ItemSelected方法时,可以判断IsSelect的值,如果值为true,可以设置一种颜色,如果值为false,可以设置另一种颜色。 感谢它运行良好,但我注意到在 android 上,当我在页面之间切换时,主菜单中的选择器不会改变。有没有办法做到这一点?

以上是关于Xamarin 列表视图选定项目更改图标颜色的主要内容,如果未能解决你的问题,请参考以下文章

设置列表视图项模板的背景颜色和列表背景颜色时,Xamarin Forms Listview 选定项背景颜色丢失

我可以以编程方式更改 Xamarin.Forms 中的 styles.xml 吗?

即使焦点在另一个控件上,如何更改列表视图选定的行背景颜色?

xml 使用Xamarin.Forms时在Android列表视图中更改所选高亮颜色的示例

ListView:如何从列表中访问视图以更改背景颜色?

如何在 Xamarin 表单中使用 MVVM 仅为集合视图中的选定框架设置颜色?