You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Grid布局点击单个卡片时所有按钮都被触发如何解决

问题根因

  • 你当前把动画控制器_controller和缩放变量_scale定义在父组件中,所有网格卡片都共用这两个变量,一旦触发动画修改_scale的值,所有绑定了该变量的卡片都会同步执行缩放效果,看起来就像所有卡片的点击事件都被触发了,实际只是所有卡片共享了同一套动画状态。
  • 补充小问题:你定义homeEnabledButtons时要求传入点击回调参数Function fun,但实际调用时没有传入,属于冗余参数,不过和当前bug无关。

修复方案

把单个网格卡片抽成独立的StatefulWidget,每个卡片自己维护自己的动画控制器和缩放状态,点击时只会修改当前卡片的动画参数,不会影响其他卡片。

示例代码:独立卡片组件

class GridCardItem extends StatefulWidget {
  final int position;
  const GridCardItem({super.key, required this.position});

  @override
  State<GridCardItem> createState() => _GridCardItemState();
}

class _GridCardItemState extends State<GridCardItem> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _scale;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 100),
    );
    _scale = Tween<double>(begin: 1.0, end: 0.9).animate(_controller);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _buttonHandler() {
    _controller.forward();
    Timer(const Duration(milliseconds: 100), () {
      _controller.reverse();
    });
    Timer(const Duration(milliseconds: 50), () {
      print("当前点击的卡片位置:${widget.position}");
      // 此处填写你自己的点击业务逻辑
    });
  }

  // 把原来的图标判断逻辑移到这里
  IconData _getIconData() {
    switch(widget.position) {
      case 0: return Icons.pie_chart;
      case 1: return Icons.perm_device_info;
      // 补全其他position对应的图标
      default: return Icons.add;
    }
  }

  // 把原来的标题判断逻辑移到这里
  String _getTitle() {
    switch(widget.position) {
      case 0: return "标题1";
      case 1: return "标题2";
      // 补全其他position对应的标题
      default: return "";
    }
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _buttonHandler,
      child: AnimatedBuilder(
        animation: _scale,
        builder: (context, child) {
          return Transform.scale(
            scale: _scale.value,
            child: homeEnabledButtons(context, _getTitle(), _getIconData()),
          );
        },
      ),
    );
  }

  // 原homeEnabledButtons方法,可移到此处或者抽为公共工具方法
  Widget homeEnabledButtons(BuildContext context, String title, IconData icon) {
    return Card(
      elevation: 10.0,
      // 替换为你自己定义的卡片颜色变量
      color: Colors.white,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(
            icon,
            // 替换为你自己定义的主题色变量
            color: Colors.blue,
            size: 100.0,
          ),
          Text(
            title,
            textAlign: TextAlign.center,
            // 替换为你自己定义的文本样式
            style: Theme.of(context).textTheme.titleSmall,
          ),
        ],
      ),
      shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.all(Radius.circular(15))),
    );
  }
}

GridView部分修改为

GridView(
  shrinkWrap: true,
  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    crossAxisSpacing: 30,
    mainAxisSpacing: 30,
  ),
  children: const [
    GridCardItem(position: 0),
    GridCardItem(position: 1),
    GridCardItem(position: 2),
    GridCardItem(position: 3),
  ],
)

内容的提问来源于stack exchange,提问作者Jason Waku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 17:39:00