CollectionView选中项图片透明度切换及选中背景透明异常问题
解决CollectionView选中项橙色背景及CheckImage透明度切换问题
我来帮你搞定这个问题~你现在遇到的橙色选中背景,是因为CollectionView的每个项都被一个SelectableItemView容器包裹,默认的选中背景色是在这个容器上的,你之前只修改了ItemTemplate里Grid的视觉状态,根本没覆盖到容器的默认样式。另外,我们可以用视觉状态来优雅实现选中时CheckImage的透明度切换,不用写太多后台代码,具体方案如下:
1. 先搞定ItemContainer的透明选中背景
我们需要给CollectionView添加ItemContainerStyle,覆盖它的默认选中状态样式:
<CollectionView x:Name="CategoryView" ItemsSource="{Binding list}" Margin="15,0,15,0" SelectionMode="Multiple" SelectionChanged="CategoryView_SelectionChanged"> <!-- 新增ItemContainerStyle,清除选中时的橙色背景 --> <CollectionView.ItemContainerStyle> <Style TargetType="SelectableItemView"> <Setter Property="VisualStateManager.VisualStateGroups"> <VisualStateGroupList> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Selected"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="Transparent"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateGroupList> </Setter> </Style> </CollectionView.ItemContainerStyle> <!-- 你原有的ItemsLayout和ItemTemplate保留不变,只需要给Grid加视觉状态 --> <CollectionView.ItemsLayout> <GridItemsLayout Orientation="Vertical" Span="2" VerticalItemSpacing="7" HorizontalItemSpacing="7"/> </CollectionView.ItemsLayout> <CollectionView.ItemTemplate> <DataTemplate> <Grid> <!-- 原Grid的布局和控件保持不变 --> <Grid.RowDefinitions> <RowDefinition Height="20"/> <RowDefinition Height="40"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Image Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="3" Source="{Binding Button}"/> <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Text="{Binding Titolo}" FontAttributes="Bold" VerticalTextAlignment="Start" TextColor="Black" Margin="20,3,0,0"/> <Image Grid.Row="1" Grid.Column="2" Source="{Binding Image}" Margin="0,0,20,10" HorizontalOptions="EndAndExpand"/> <Image x:Name="CheckImage" Grid.Row="1" Grid.Column="0" Source="{Binding Check}" Margin="20,0,0,0" Opacity="0"/> <!-- 2. 给Grid添加视觉状态,控制CheckImage的透明度 --> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Selected"> <VisualState.Setters> <Setter TargetName="CheckImage" Property="Opacity" Value="1"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView>
关键细节解释
- ItemContainerStyle的作用:CollectionView的每个列表项都会被
SelectableItemView包裹,这个容器自带选中时的橙色背景,所以必须在这里把选中状态的背景设为透明,才能完全去掉橙色。 - Grid内的视觉状态:通过
TargetName直接指定CheckImage,当项被选中时自动把透明度从0改成1,完全用XAML声明式实现,不需要在后台写复杂的SelectionChanged逻辑。
备选方案:用代码事件处理(如果你更习惯这种方式)
如果你偏好后台代码控制,也可以在CategoryView_SelectionChanged事件里手动处理:
private void CategoryView_SelectionChanged(object sender, SelectionChangedEventArgs e) { // 处理新选中的项 foreach (var selectedItem in e.CurrentSelection) { var itemContainer = CategoryView.ItemContainerGenerator.ContainerFromItem(selectedItem) as SelectableItemView; if (itemContainer != null) { // 清除容器的橙色背景 itemContainer.BackgroundColor = Color.Transparent; // 找到Grid里的CheckImage并修改透明度 var itemGrid = itemContainer.Content as Grid; var checkImg = itemGrid?.FindByName<Image>("CheckImage"); checkImg.Opacity = 1; } } // 处理取消选中的项 foreach (var unselectedItem in e.PreviousSelection) { var itemContainer = CategoryView.ItemContainerGenerator.ContainerFromItem(unselectedItem) as SelectableItemView; if (itemContainer != null) { var itemGrid = itemContainer.Content as Grid; var checkImg = itemGrid?.FindByName<Image>("CheckImage"); checkImg.Opacity = 0; } } }
不过还是更推荐第一种XAML的方式,代码更简洁,也符合Xamarin.Forms的声明式设计理念。
内容的提问来源于stack exchange,提问作者Stefano Ston
相关产品推荐
相关产品推荐

