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

Flutter中按下按钮弹窗时,如何禁用Column组件内所有按钮?

实现Flutter动态按钮组的全局禁用(按下按钮到弹窗关闭期间)

你当前的代码中每个按钮单独维护isButtonEnabled状态,只能禁用当前点击的按钮,无法实现全局禁用所有按钮的需求。要解决这个问题,需要把全局禁用状态提升到父组件的State中,统一控制所有按钮的可点击性,并且等待弹窗关闭后再恢复按钮状态。

具体实现步骤:

  1. 在父组件的State类中添加全局状态变量:
bool isGlobalProcessing = false;
  1. 移除每个按钮内部的isButtonEnabled变量,所有按钮的onPressed判断都依赖这个全局状态。

  2. 在按钮点击逻辑中,先设置全局状态为禁用,执行API请求和打印操作后,使用await等待弹窗关闭(showDialog返回Future,弹窗关闭时Future才会完成),最后恢复全局状态。

修改后的完整代码片段:

// 注意:isGlobalProcessing需要定义在当前页面的State类中
bool isGlobalProcessing = false;
int isLoadingIndex = -1;

// ... 其他代码 ...

FutureBuilder<Map<String, dynamic>>(
  future: _apiService.fetchData(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(child: CircularProgressIndicator());
    }
    if (snapshot.hasError || !snapshot.hasData) {
      return Center(child: Text('Error: ${snapshot.error ?? "No data"}'));
    }
    final String companyName = snapshot.data!['company']?.name ?? '';
    final List<dynamic> categoriesData = snapshot.data!['categories'] ?? [];

    return Column(
      children: categoriesData.map<Widget>((category) {
        final String nameEn = category.nameEn;
        final String nameBn = category.nameBn;
        bool isProcessing = false;

        return StatefulBuilder(
          builder: (context, setState) {
            final bool isSelected = isLoadingIndex == categoriesData.indexOf(category);

            return Column(
              children: [
                ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Theme.of(context).colorScheme.primary,
                    fixedSize: Size(screenWidth * 0.8, screenHeight * 0.1),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(5),
                    ),
                  ),
                  onPressed: isGlobalProcessing ? null : () async {
                    // 设置全局禁用状态
                    setState(() {
                      isGlobalProcessing = true;
                      isLoadingIndex = categoriesData.indexOf(category);
                      isProcessing = true;
                    });
                    
                    final int categoryID = category.id;
                    final url = URL;
                    final response = await http.get(Uri.parse(url));

                    if (response.statusCode == 200) {
                      final responseData = json.decode(response.body);
                      print(responseData);
                      final data = responseData['data'];
                      final Token = data['token'];
                      final Time = data['time'];
                      print('Token: $Token, Time and Date: $Time');

                      final SunmiPosSdk sunmiPosSdk = SunmiPosSdk();
                      await sunmiPosSdk.printReceipt(context, '$Token', '$Time', '$nameEn', '$nameBn', '$companyName');

                      // await弹窗,等待弹窗关闭
                      await showDialog(
                        context: context,
                        barrierColor: Colors.grey.withOpacity(0.5),
                        barrierDismissible: false,
                        builder: (BuildContext context) {
                          return Center(
                            child: buildAlertDialog(Token, Time, '$nameEn ($nameBn)'),
                          );
                        },
                      );
                    } else {
                      print('Failed to fetch data: ${response.statusCode}');
                    }
                    
                    // 弹窗关闭后恢复全局状态
                    setState(() {
                      isGlobalProcessing = false;
                      isLoadingIndex = -1;
                      isProcessing = false;
                    });
                  },
                  child: FittedBox(
                    fit: BoxFit.scaleDown,
                    child: Text(
                      '$nameEn ($nameBn)',
                      style: const TextStyle(
                        fontSize: 25,
                        fontWeight: FontWeight.bold,
                        color: Colors.white,
                      ),
                    ),
                  ),
                ),
                if (isProcessing)
                  GestureDetector(
                    onTap: () {},
                    child: Container(
                      color: Colors.transparent,
                    ),
                  ),
                SizedBox(height: screenHeight * 0.01),
              ],
            );
          },
        );
      }).toList(),
    );
  },
),

关键说明:

  • 全局状态控制:isGlobalProcessing是父State中的变量,所有按钮的onPressed都依赖它,确保任何一个按钮点击后,所有按钮都会被禁用。
  • 等待弹窗关闭:使用await showDialog(),确保只有当用户关闭弹窗后,才会执行恢复按钮状态的代码,完全覆盖“按钮按下到弹窗关闭”的时间段。
  • 局部状态保留:isProcessing和isLoadingIndex可以保留,用于显示当前按钮的加载状态(比如加载动画)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:42:17