.NET MAUI实现ListView条目点击缩放动画的问题
.NET MAUI ListView条目点击缩放动画失效的解决方法
在.NET MAUI中使用ListView时,想要实现点击条目时先放大再缩小的动画效果,已获取到ViewCell及其内部的Grid,但修改Scale属性后无效果,怀疑是ListView的渲染机制导致后续修改不触发重新渲染。
原XAML代码
<?xml version="1.0" encoding="utf-8" ?> <ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="GakugoMAUI.Views.LessonListView"> <ContentView.Resources> <ResourceDictionary> <DataTemplate x:Key="LessonButton"> <ViewCell> <Grid Scale="1"> <BoxView HorizontalOptions="Fill" VerticalOptions="Fill" CornerRadius="10" Color="{AppThemeBinding Light={StaticResource Gray100}, Dark={StaticResource Gray750}}"/> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="20"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="10"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Image VerticalOptions="Fill" Margin="15,0,0,0" Scale="1.1" Grid.Column="0"> <Image.Source> <FontImageSource Glyph="{Binding Glyph}" FontFamily="{Binding GlyphFontFamily}" Color="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Secondary}}"/> </Image.Source> </Image> <Grid Grid.Column="2"> <Grid.RowDefinitions> <RowDefinition Height="10"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> <RowDefinition Height="10"/> </Grid.RowDefinitions> <Label Text="{Binding TitleText}" FontSize="16" Grid.Row="1"/> <Label Text="{Binding SubtitleText}" FontSize="12" FontAttributes="Italic" Grid.Row="2"/> </Grid> </Grid> </Grid> </ViewCell> </DataTemplate> </ResourceDictionary> </ContentView.Resources> <Grid> <ListView x:Name="lessonsList" ItemsSource="{Binding LessonButtons}" ItemTemplate="{StaticResource LessonButton}" ItemTapped="LessonButton_Clicked" Margin="10" Grid.Row="3"/> </Grid> </ContentView>
原点击处理代码
public async void LessonButton_Clicked(object sender, ItemTappedEventArgs e) { if (sender is ListView list) { var cells = list.GetVisualTreeDescendants().Where(x => x.GetType() == typeof(ViewCell)); Grid currentItem = (Grid)((ViewCell)cells.ElementAt(e.ItemIndex)).View; await currentItem.ScaleTo(1.5); await currentItem.ScaleTo(1); } }
解决方案
问题核心是获取当前点击Cell的方式错误:ListView采用ViewCell复用机制,通过遍历VisualTree并按索引取Cell的方法,无法保证拿到用户实际点击的条目(滚动后索引对应关系会混乱)。正确做法是使用ListView的GetCell方法获取当前Item对应的ViewCell。
修改后的点击处理代码
public async void LessonButton_Clicked(object sender, ItemTappedEventArgs e) { if (sender is ListView listView && e.Item != null) { // 获取当前点击Item对应的ViewCell var viewCell = (ViewCell)listView.GetCell(e.Item); if (viewCell?.View is Grid itemGrid) { // 先重置缩放状态,避免重复点击出现异常 itemGrid.Scale = 1; // 执行放大动画(150ms完成,可根据需求调整时间) await itemGrid.ScaleTo(1.5, 150); // 执行缩小动画 await itemGrid.ScaleTo(1, 150); } } }
优化补充
如果要避免重复点击导致的动画冲突,可以在动画开始前取消未完成的动画:
public async void LessonButton_Clicked(object sender, ItemTappedEventArgs e) { if (sender is ListView listView && e.Item != null) { var viewCell = (ViewCell)listView.GetCell(e.Item); if (viewCell?.View is Grid itemGrid) { // 取消之前未完成的动画 await itemGrid.CancelAnimations(); itemGrid.Scale = 1; await itemGrid.ScaleTo(1.5, 150); await itemGrid.ScaleTo(1, 150); } } }
内容的提问来源于stack exchange,提问作者joeatethebeans
相关产品推荐
相关产品推荐

