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

Flutter开发中点击GridView选色如何修改目标CircleBorder的颜色

Flutter 圆形颜色同步更新修复方案

初始页面默认展示的黄色圆形效果:
黄色初始圆形
点击后弹出的颜色选择GridView效果:
颜色选择弹窗

问题原因

  • 未声明可变状态变量存储选中的颜色,直接使用不可修改的全局常量kMainColor作为圆形颜色值,无法触发UI更新
  • GridView内颜色按钮的点击回调为空逻辑,没有将选中的颜色赋值给对应状态
  • dispose方法执行顺序错误,先销毁FocusNode再移除监听,存在空调用风险

修复步骤

  1. 新增状态变量存储当前选中颜色
    在_NewCounterState类中新增如下变量,默认值可按需调整:
// 新增状态变量,默认设置为黄色和初始效果对齐
Color selectedColor = Color(0xFFFFEB3C);
  1. 替换原有圆形的颜色取值
    将原有RaisedButton的color属性从kMainColor替换为selectedColor
  2. 补全颜色选择按钮的点击逻辑
    在GridView的MaterialButton的onPressed回调中,将选中的颜色赋值给selectedColor
  3. 调整dispose方法执行顺序,先移除监听再销毁FocusNode

完整修改后代码

class NewCounter extends StatefulWidget {
  @override
  _NewCounterState createState() => _NewCounterState();
}
class _NewCounterState extends State<NewCounter> {
  final FocusNode textNode = FocusNode();
  final FocusNode numberNode = FocusNode();
  TextStyle labelStyle;
  TextStyle numberStyle;
  // 新增存储选中颜色的状态变量
  Color selectedColor = Color(0xFFFFEB3C);
  List<Color> colorsList = [
    Color(0xFFF44236),
    Color(0xFFEA1E63),
    Color(0xFF9C28B1),
    Color(0xFF673BB7),
    Color(0xFF3F51B5),
    Color(0xFF2196F3),
    Color(0xFF03A9F5),
    Color(0xFF00BCD5),
    Color(0xFF009788),
    Color(0xFF4CB050),
    Color(0xFF8BC24A),
    Color(0xFFCDDC39),
    Color(0xFFFFEB3C),
    Color(0xFFFEC107),
    Color(0xFFFF9700),
    Color(0xFFFE5722),
    Color(0xFF795547),
    Color(0xFF9E9E9E),
    Color(0xFF607D8B),
    Color(0xFF000000),
  ];
  @override
  void initState() {
    super.initState();
    textNode.addListener(onFocusChange);
  }
  void onFocusChange() {
    setState(() {
      labelStyle = textNode.hasFocus ? TextStyle(color: selectedColor) : null;
      numberStyle = numberNode.hasFocus ? TextStyle(color: selectedColor) : null;
    });
  }
  @override
  void dispose() {
    // 先移除监听再销毁节点
    textNode.removeListener(onFocusChange);
    textNode.dispose();
    numberNode.dispose();
    super.dispose();
  }
  Widget build(BuildContext context) => MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(
            backgroundColor: selectedColor,
            leading: IconButton(
                icon: Icon(
                  Icons.close,
                  color: Colors.black,
                ),
                onPressed: () {
                  Navigator.push(
                    context,
                    PageTransition(
                      type: PageTransitionType.rightToLeft,
                      duration: Duration(milliseconds: 500),
                      child: CountNumbering(),
                    ),
                  );
                }),
            title: Text(
              'New Counter',
              style: TextStyle(
                color: Colors.black,
              ),
            ),
            actions: [
              IconButton(
                  icon: Image.asset(
                    'assets/images/floppy-disk.png',
                    width: 20.0,
                    height: 20.0,
                  ),
                  onPressed: () {
                    Navigator.pop(context);
                  }),
            ],
          ),
          body: Container(
            child: Column(
              children: [
                Column(
                  children: [
                    Padding(
                      padding: const EdgeInsets.only(
                          left: 15.0, top: 15.0, right: 15.0, bottom: 0.0),
                      child: TextFormField(
                        focusNode: textNode,
                        cursorColor: selectedColor,
                        decoration: InputDecoration(
                          filled: true,
                          fillColor: Color(0xFFE0E0E0),
                          labelText: 'Name',
                          labelStyle: labelStyle,
                          enabledBorder: UnderlineInputBorder(
                            borderSide: BorderSide(
                              color: Color(0xFF5A5A5A),
                            ),
                          ),
                          focusedBorder: UnderlineInputBorder(
                            borderSide: BorderSide(
                              color: selectedColor,
                            ),
                          ),
                        ),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(
                          left: 15.0, top: 0.0, right: 15.0, bottom: 15.0),
                      child: TextFormField(
                        focusNode: numberNode,
                        keyboardType: TextInputType.number,
                        inputFormatters: <TextInputFormatter>[
                          FilteringTextInputFormatter.digitsOnly
                        ],
                        cursorColor: selectedColor,
                        decoration: InputDecoration(
                          filled: true,
                          fillColor: Color(0xFFE0E0E0),
                          labelText: 'Start value',
                          labelStyle: numberStyle,
                          enabledBorder: UnderlineInputBorder(
                            borderSide: BorderSide(
                              color: Color(0xFF5A5A5A),
                            ),
                          ),
                          focusedBorder: UnderlineInputBorder(
                            borderSide: BorderSide(
                              color: selectedColor,
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                SizedBox(
                  height: 10.0,
                ),
                Row(
                  children: [
                    SizedBox(
                      width: 33.0,
                    ),
                    Text(
                      'Select a Color',
                      style: TextStyle(
                        fontSize: 16.0,
                      ),
                    ),
                    SizedBox(
                      width: 10.0,
                    ),
                    Container(
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: Colors.black,
                        boxShadow: [
                          BoxShadow(
                            color: Colors.black54,
                            spreadRadius: 2,
                            blurRadius: 2,
                          ),
                        ],
                      ),
                      child: RaisedButton(
                        child: Padding(
                          padding: EdgeInsets.all(40.0),
                        ),
                        onPressed: () {
                          showDialog(
                            context: context,
                            builder: (BuildContext context) => Dialog(
                              child: Container(
                                child: GridView.builder(
                                  padding: const EdgeInsets.all(5.0),
                                  shrinkWrap: true,
                                  itemCount: colorsList.length,
                                  gridDelegate:
                                      SliverGridDelegateWithFixedCrossAxisCount(
                                          childAspectRatio: 1.0,
                                          crossAxisSpacing: 5.0,
                                          mainAxisSpacing: 5.0,
                                          crossAxisCount: 5),
                                  itemBuilder: (context, index) {
                                    var color = colorsList[index];
                                    return MaterialButton(
                                        elevation: 0,
                                        color: color,
                                        shape: CircleBorder(),
                                        onPressed: () {
                                          Navigator.pop(context);
                                          // 赋值选中的颜色
                                          setState(() {
                                            selectedColor = color;
                                          });
                                        });
                                  },
                                ),
                              ),
                            ),
                          );
                        },
                        shape: CircleBorder(),
                        // 替换为状态变量
                        color: selectedColor,
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 12:45:02