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

Flutter开发:全局计数器达12时如何禁用加法按钮?

问题描述

我创建了3个计数器,前两个各配有加减按钮,单个计数器的最大值为8,且二者都会影响最大值为12的全局计数器(globalCounter)。当前遇到的问题是:当globalCounter达到12时,如何让两个加法按钮停止工作?例如,当counterOne为7时,counterTwo加到5时全局计数器将达到12,此时需禁用counterTwo的加法按钮。

按钮效果示例

以下是我的代码:

void main() {
  runApp(
    const MyApp(),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        body: SafeArea(child: ButtonProblem()),
      ),
    );
  }
}

class ButtonProblem extends StatefulWidget {
  const ButtonProblem({Key? key}) : super(key: key);

  @override
  State<ButtonProblem> createState() => _ButtonProblemState();
}

class _ButtonProblemState extends State<ButtonProblem> {
  int counterOne = 0;
  int counterTwo = 0;
  int globalCounter = 0;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                onTap: () {
                  setState(() {
                    if (counterOne > 0) counterOne--;
                    if (globalCounter > 0) globalCounter--;
                  });
                },
                child: Container(
                  child: Icon(Icons.remove, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  color: Colors.blueGrey[900],
                ),
              ),
            ),
            Container(
              child: Text(
                '$counterOne',
                style: TextStyle(
                  fontFamily: 'SourceSansPro',
                  fontSize: 40.0,
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                onTap: () {
                  setState(() {
                    if (counterOne < 8) counterOne++;
                    if (globalCounter < 12) globalCounter++;
                  });
                },
                child: Container(
                  child: Icon(Icons.add, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  color: Colors.blueGrey[900],
                ),
              ),
            ),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                onTap: () {
                  setState(() {
                    if (counterTwo > 0) counterTwo--;
                    if (globalCounter > 0) globalCounter--;
                  });
                },
                child: Container(
                  child: Icon(Icons.remove, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  color: Colors.blueGrey[900],
                ),
              ),
            ),
            Container(
              child: Text(
                '$counterTwo',
                style: TextStyle(
                  fontFamily: 'SourceSansPro',
                  fontSize: 40.0,
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                onTap: () {
                  setState(() {
                    if (counterTwo < 8) counterTwo++;
                    if (globalCounter < 12) globalCounter++;
                  });
                },
                child: Container(
                  child: Icon(Icons.add, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  color: Colors.blueGrey[900],
                ),
              ),
            ),
          ],
        ),
        Container(
          child: Center(
            child: Text(
              '$globalCounter/12',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontFamily: 'SourceSansPro',
                fontSize: 35.0,
                color: Colors.white,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        ),
      ],
    );
  }
}
解决方案

要实现需求,需要同时判断两个条件才允许加法按钮触发:单个计数器未达上限(8),且全局计数器未达上限(12)。另外,给禁用状态的按钮设置灰色,让用户直观感知按钮状态。

修改后的完整代码如下:

void main() {
  runApp(
    const MyApp(),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        body: SafeArea(child: ButtonProblem()),
      ),
    );
  }
}

class ButtonProblem extends StatefulWidget {
  const ButtonProblem({Key? key}) : super(key: key);

  @override
  State<ButtonProblem> createState() => _ButtonProblemState();
}

class _ButtonProblemState extends State<ButtonProblem> {
  int counterOne = 0;
  int counterTwo = 0;
  int globalCounter = 0;
  
  // 判断counterOne的加按钮是否可点击
  bool get canIncrementOne => counterOne < 8 && globalCounter < 12;
  // 判断counterTwo的加按钮是否可点击
  bool get canIncrementTwo => counterTwo < 8 && globalCounter < 12;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                onTap: () {
                  setState(() {
                    if (counterOne > 0) counterOne--;
                    if (globalCounter > 0) globalCounter--;
                  });
                },
                child: Container(
                  child: Icon(Icons.remove, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  color: Colors.blueGrey[900],
                ),
              ),
            ),
            Container(
              child: Text(
                '$counterOne',
                style: TextStyle(
                  fontFamily: 'SourceSansPro',
                  fontSize: 40.0,
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                // 只有可点击时才响应事件
                onTap: canIncrementOne
                    ? () {
                        setState(() {
                          counterOne++;
                          globalCounter++;
                        });
                      }
                    : null,
                child: Container(
                  child: Icon(Icons.add, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  // 根据状态设置按钮颜色
                  color: canIncrementOne ? Colors.blueGrey[900] : Colors.grey[700],
                ),
              ),
            ),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                onTap: () {
                  setState(() {
                    if (counterTwo > 0) counterTwo--;
                    if (globalCounter > 0) globalCounter--;
                  });
                },
                child: Container(
                  child: Icon(Icons.remove, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  color: Colors.blueGrey[900],
                ),
              ),
            ),
            Container(
              child: Text(
                '$counterTwo',
                style: TextStyle(
                  fontFamily: 'SourceSansPro',
                  fontSize: 40.0,
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
            ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: InkWell(
                onTap: canIncrementTwo
                    ? () {
                        setState(() {
                          counterTwo++;
                          globalCounter++;
                        });
                      }
                    : null,
                child: Container(
                  child: Icon(Icons.add, color: Colors.white),
                  width: 25.0,
                  height: 35.0,
                  color: canIncrementTwo ? Colors.blueGrey[900] : Colors.grey[700],
                ),
              ),
            ),
          ],
        ),
        Container(
          margin: const EdgeInsets.only(top: 20),
          child: Center(
            child: Text(
              '$globalCounter/12',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontFamily: 'SourceSansPro',
                fontSize: 35.0,
                color: Colors.white,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        ),
      ],
    );
  }
}

关键修改点

  • 新增两个getter方法canIncrementOne和canIncrementTwo,统一判断按钮是否可点击的逻辑,代码更简洁易维护
  • 加法按钮的onTap根据判断结果设置为事件回调或null,null时InkWell会自动禁用点击
  • 根据可点击状态设置按钮背景色,禁用时显示灰色,提升交互反馈

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:01:13