Flutter GridView Item点击动画问题:点击单个item所有项同时动画如何修复
问题根因
你当前的代码中整个页面State只持有一个全局共享的动画控制器和动画实例,所有GridView的item都绑定了同一个动画参数,只要触发控制器,所有绑定了该动画的组件都会同步执行动画,所以会出现点击任意item所有项一起动的问题。
解决方案
最优方案是将单个Grid项抽离为独立的Stateful组件,每个组件内部自行管理自己的动画控制器,实现每个item的动画独立互不干扰,修改代码如下:
首先抽离独立的Grid Item组件:
// 独立管理自身动画的Grid Item组件 class PetGridItem extends StatefulWidget { final String assetUrl; // 如果需要向外传递点击事件可增加onTap回调参数 const PetGridItem({super.key, required this.assetUrl}); @override State<PetGridItem> createState() => _PetGridItemState(); } class _PetGridItemState extends State<PetGridItem> with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation<double> _animation; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 500), ); _animation = Tween<double>(begin: 1.0, end: 1.2).animate(_animationController); _animation.addStatusListener((status) { if (status == AnimationStatus.completed) { _animationController.reverse(); } }); } @override void dispose() { // 销毁控制器避免内存泄漏 _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Card( clipBehavior: Clip.antiAliasWithSaveLayer, shape: const CircleBorder(), elevation: 5.0, shadowColor: CustomColor.mailColor, child: InkResponse( onTap: (){ // 仅触发当前item的动画 _animationController.forward(); }, child: ScaleTransition( scale: _animation, child: Image.asset( widget.assetUrl, fit: BoxFit.cover, height: 70.0, width: 70.0, ), ), ), ); } }
然后修改原页面的代码,移除全局动画相关逻辑,直接调用抽离好的组件:
class ChoosePetState extends State with TickerProviderStateMixin { @override void initState() { super.initState(); } @override Widget build(BuildContext context) { SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle(statusBarColor: CustomColor.mailColor)); return SafeArea( child: Scaffold( body: CustomScrollView( slivers: <Widget>[ SliverToBoxAdapter( child: SizedBox( width: double.infinity, child: Padding( padding: const EdgeInsets.fromLTRB(20.0, 20.0,20.0,30.0), child: Text( Strings.choosePet, style: GoogleFonts.firaSans( fontSize: 32.0, fontWeight: FontWeight.bold, color: CustomColor.colorPrimaryDark.withOpacity(0.7), ), ), ), ), ), SliverPadding( padding: const EdgeInsets.fromLTRB(10.0,0.0,10.0,30.0), sliver: SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, childAspectRatio: 0.91, mainAxisSpacing: 1.0, crossAxisSpacing: 1.0, ), delegate: SliverChildBuilderDelegate( (context, index) { return PetGridItem(assetUrl: list[index].url); }, childCount: list.length, ), ), ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者shubham maurya
相关产品推荐
相关产品推荐

