Flutter菜单动画触发问题:点击单个按钮所有动画同时启动如何解决
问题原因
你目前所有按钮共用同一个全局selected布尔状态,只要这个状态更新,所有绑定了这个状态的AnimatedContainer都会同步响应,所以才会出现点一个所有按钮都同步动的情况。
解决方案
把单布尔状态替换为能区分每个按钮选中状态的存储结构,这里提供两种常用实现:
- 单选模式:一次只能有一个按钮处于选中状态,用存储当前选中索引的变量实现
- 多选模式:允许多个按钮同时选中,用布尔数组实现
这里以最常用的单选模式为例,修改后的代码如下:
修改后的main.dart
import 'package:flutter/material.dart'; import './button.dart'; void main() => runApp(const MyStatefulWidget()); class MyStatefulWidget extends StatefulWidget { const MyStatefulWidget({Key? key}) : super(key: key); @override State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); } class _MyStatefulWidgetState extends State<MyStatefulWidget> { // 替换原来的单布尔变量,存储当前选中的索引,null表示没有选中项 int? selectedIndex; Container countryPageView() { final PageController controller = PageController(initialPage: 1, keepPage: true, viewportFraction: 0.35); return Container( height: 300, child: PageView.builder( scrollDirection: Axis.horizontal, controller: controller, itemCount: 5, physics: const BouncingScrollPhysics(), itemBuilder: (BuildContext context, int index) { return Container( child: gestureDetectorOntap(index), ); }, ), ); } GestureDetector gestureDetectorOntap(int index) { return GestureDetector( onTap: () { setState(() { // 如果点击的是已选中的按钮就取消选中,否则选中当前点击的按钮 selectedIndex = selectedIndex == index ? null : index; }); }, child: Column( children: [Text('menu $index'), button(selectedIndex == index)], // 只有当前索引匹配时才传选中状态true ), ); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: countryPageView(), ), ); } }
可选优化(button.dart规范调整)
你现有button.dart可以直接复用无需修改,如果要符合Flutter官方开发规范,建议改成无状态Widget形式:
import 'package:flutter/material.dart'; class AnimatedMenuButton extends StatelessWidget { final bool selected; const AnimatedMenuButton({super.key, required this.selected}); @override Widget build(BuildContext context) { return AnimatedContainer( width: selected ? 200.0 : 100.0, height: selected ? 100.0 : 200.0, color: selected ? Colors.red : Colors.blue, alignment: selected ? Alignment.center : AlignmentDirectional.topCenter, duration: const Duration(seconds: 2), curve: Curves.fastOutSlowIn, child: const FlutterLogo(size: 75), ); } }
如果需要实现多选效果,只需要把状态换成List<bool> selectedList = List.generate(5, (_) => false);,点击事件改成selectedList[index] = !selectedList[index];,传参时用button(selectedList[index])即可。
内容的提问来源于stack exchange,提问作者user5824983
相关产品推荐
相关产品推荐

