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
相关产品推荐
相关产品推荐

