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

Flutter动态生成按钮的onPressed回调处理及点击变色需求

Hey there! Let's fix this step by step since you're new to Flutter—no worries, this is a common gotcha when dealing with dynamic buttons and state.

First, let's break down what's missing in your current code:

  • You're using currentHour to track the active button, but you're not updating it when a button is pressed (and triggering a UI rebuild to reflect the change).
  • There's also a potential closure trap in your for loop: if you run your current code, clicking any button might print the last value of i (17) instead of the actual hour you clicked. That's because the i variable in the onPressed callback references the same loop variable, which gets updated each iteration.

Here's the corrected approach:

Step 1: Make sure currentHour is a state variable

First, your widget needs to be a StatefulWidget (since we need to update the UI when state changes). In your State class, define:

int currentHour = 8; // Set your initial active hour here

Step 2: Rewrite the button list with proper state handling

Instead of a for loop adding to a list, use List.generate—this avoids the closure issue because each iteration gets its own independent hour variable. Then, update currentHour inside setState when a button is pressed:

List<Widget> workingHoursButtons() {
  // Generate 10 buttons (8 to 17 inclusive)
  return List.generate(10, (index) {
    final hour = 8 + index;
    
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: SizedBox(
        width: 59.0,
        height: 50.0,
        child: TextButton( // Note: FlatButton is deprecated, use TextButton instead
          style: TextButton.styleFrom(
            backgroundColor: hour == currentHour ? Color(0xff425660) : null,
            shape: RoundedRectangleBorder(
              side: BorderSide(),
              borderRadius: BorderRadius.circular(3.0),
            ),
          ),
          child: Text(
            "$hour",
            style: TextStyle(
              color: hour == currentHour ? Colors.white : null,
              fontSize: 16.0,
              fontWeight: FontWeight.bold,
            ),
          ),
          onPressed: hour < currentHour 
              ? null 
              : () {
                  setState(() {
                    currentHour = hour;
                  });
                },
        ),
      ),
    );
  });
}

Key changes explained:

  • List.generate: Creates each button with a unique hour variable, so the onPressed callback always references the correct hour for that button.
  • setState: Calling this tells Flutter that the state has changed, so it will rebuild the UI—this is what updates the button's background color when you click it.
  • Replaced FlatButton: FlatButton is no longer recommended; TextButton with styleFrom is the modern way to customize button appearance.

Bonus: If you need multi-select instead of single-select

If you want users to select multiple hours (e.g., a range), change currentHour to a Set<int>:

Set<int> selectedHours = {8}; // Initial selected hour

Then update the button logic:

// In the button style:
backgroundColor: selectedHours.contains(hour) ? Color(0xff425660) : null,

// In onPressed:
onPressed: hour < currentHour // Or remove this if all buttons are selectable
    ? null 
    : () {
        setState(() {
          if (selectedHours.contains(hour)) {
            selectedHours.remove(hour);
          } else {
            selectedHours.add(hour);
          }
        });
      },

That should do it! Let me know if you run into any other issues as you learn Flutter.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:26:54