Flutter开发中点击GridView选色如何修改目标CircleBorder的颜色
Flutter 圆形颜色同步更新修复方案
初始页面默认展示的黄色圆形效果:
点击后弹出的颜色选择GridView效果:
问题原因
- 未声明可变状态变量存储选中的颜色,直接使用不可修改的全局常量
kMainColor作为圆形颜色值,无法触发UI更新 - GridView内颜色按钮的点击回调为空逻辑,没有将选中的颜色赋值给对应状态
dispose方法执行顺序错误,先销毁FocusNode再移除监听,存在空调用风险
修复步骤
- 新增状态变量存储当前选中颜色
在_NewCounterState类中新增如下变量,默认值可按需调整:
// 新增状态变量,默认设置为黄色和初始效果对齐 Color selectedColor = Color(0xFFFFEB3C);
- 替换原有圆形的颜色取值
将原有RaisedButton的color属性从kMainColor替换为selectedColor - 补全颜色选择按钮的点击逻辑
在GridView的MaterialButton的onPressed回调中,将选中的颜色赋值给selectedColor - 调整
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
相关产品推荐
相关产品推荐

