import 'package:flutter/material.dart'; /// 温度显示 -- ok class TemperatureIndication extends StatefulWidget { final ValueChanged<int> valueChanged; final int choosedItem; TemperatureIndication({this.valueChanged, this.choosedItem = 0}); @override _TemperatureIndicationState createState() => _TemperatureIndicationState(); } class _TemperatureIndicationState extends State<TemperatureIndication> { int _choosedItem = 0; @override void initState() { super.initState();
// 错误点在这里 _choosedItem = widget.choosedItem; print('_TemperatureIndicationState initState:$_choosedItem'); } @override Widget build(BuildContext context) { // _choosedItem = widget.choosedItem; // print('_TemperatureIndicationState build:$_choosedItem'); return _buildItem(); } Widget _buildItem() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 32.0), child: Column( children: <Widget>[ _buildTextItem(), Padding(padding: const EdgeInsets.only(top: 4.0)), _buildButtonItem(), ], ), ); } Widget _buildTextItem() { return Row( children: <Widget>[ Expanded( child: Center(child: Text('切')), ), Expanded( child: Center(child: Text('低')), ), Expanded( child: Center(child: Text('中')), ), Expanded( child: Center(child: Text('高')), ), ], ); } Widget _buildButtonItem() { return DecoratedBox( decoration: BoxDecoration(border: Border.all( 1.5, color: Color(0xffd6def1))), child: Row( children: <Widget>[ Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _choosedItem = 0; setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(0); } }, child: DecoratedBox( decoration: _choosedItem == 0 ? BoxDecoration( color: Colors.grey, ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _choosedItem = 1; setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(1); } }, child: DecoratedBox( decoration: _choosedItem == 1 ? BoxDecoration( color: Color(0xfffe0007), ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _choosedItem = 2; setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(2); } }, child: DecoratedBox( decoration: _choosedItem == 2 ? BoxDecoration( color: Color(0xfffe0007), ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _choosedItem = 3; setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(3); } }, child: DecoratedBox( decoration: _choosedItem == 3 ? BoxDecoration( color: Color(0xfffe0007), ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), ], ), ); } }
测试代码:
@override Widget build(BuildContext context) { print('父类build问题:$chooseItem'); return Scaffold( appBar: AppBar(), body: TemperatureIndication( valueChanged: (i) { chooseItem = i; print('点击选中的值:$chooseItem'); chooseItem = 0; print('强制更改的值:$chooseItem'); setState(() {}); }, choosedItem: chooseItem, ), ); }
简单功能:就是把选中的值返回给调用者
问题描述:在返回值函数里,强制把选中的值改为 0,发现没有效果?
结论:按照官网的文档说法,widget会由架构来判断是否会刷新,判断会刷新了才刷新。刚好,我这种写法是被判断为不刷新。
@override void initState() { super.initState(); _choosedItem = widget.choosedItem; print('_TemperatureIndicationState initState:$_choosedItem'); }
问题出在以上代码中。我在State类重新定义了一个属性在initState函数中接收StatefulWidget的属性,导致的出现这样子的问题。
正确的做法是在State的build方法中直接使用StatefulWidget的属性。即是widget.choosedItem在build方法中直接使用。
原因:State的initState只执行了一次,后面StatefulWidget的choosedItem更改了,但是没有再次执行initState方法,导致_choosedItem没有跟着更改。所以界面就不会跟着更改。
结论:StatefulWidget是State的配置文件,在State中直接使用StatefulWidget的属性。
以上代码改为:
import 'package:flutter/material.dart'; /// 温度显示 -- ok class TemperatureIndication extends StatefulWidget { final ValueChanged<int> valueChanged; final int choosedItem; TemperatureIndication({this.valueChanged, this.choosedItem = 0}); @override _TemperatureIndicationState createState() => _TemperatureIndicationState(); } class _TemperatureIndicationState extends State<TemperatureIndication> { @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return _buildItem(); } Widget _buildItem() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 32.0), child: Column( children: <Widget>[ _buildTextItem(), Padding(padding: const EdgeInsets.only(top: 4.0)), _buildButtonItem(), ], ), ); } Widget _buildTextItem() { return Row( children: <Widget>[ Expanded( child: Center(child: Text('切')), ), Expanded( child: Center(child: Text('低')), ), Expanded( child: Center(child: Text('中')), ), Expanded( child: Center(child: Text('高')), ), ], ); } Widget _buildButtonItem() { return DecoratedBox( decoration: BoxDecoration(border: Border.all( 1.5, color: Color(0xffd6def1))), child: Row( children: <Widget>[ Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(0); } }, child: DecoratedBox( decoration: widget.choosedItem == 0 ? BoxDecoration( color: Colors.grey, ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(1); } }, child: DecoratedBox( decoration: widget.choosedItem == 1 ? BoxDecoration( color: Color(0xfffe0007), ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(2); } }, child: DecoratedBox( decoration: widget.choosedItem == 2 ? BoxDecoration( color: Color(0xfffe0007), ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() {}); if (widget.valueChanged != null) { widget.valueChanged(3); } }, child: DecoratedBox( decoration: widget.choosedItem == 3 ? BoxDecoration( color: Color(0xfffe0007), ) : BoxDecoration(), child: Container( height: 28.0, ), ), ), ), ], ), ); } }