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(width: 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, ), ); }
簡單功能:就是把選中的值返回給調用者app
問題描述:在返回值函數裏,強制把選中的值改成 0,發現沒有效果?ide
結論:按照官網的文檔說法,widget會由架構來判斷是否會刷新,判斷會刷新了才刷新。恰好,我這種寫法是被判斷爲不刷新。函數
@override void initState() { super.initState(); _choosedItem = widget.choosedItem; print('_TemperatureIndicationState initState:$_choosedItem'); }
問題出在以上代碼中。我在State類從新定義了一個屬性在initState函數中接收StatefulWidget的屬性,致使的出現這樣子的問題。測試
正確的作法是在State的build方法中直接使用StatefulWidget的屬性。便是widget.choosedItem在build方法中直接使用。ui
緣由:State的initState只執行了一次,後面StatefulWidget的choosedItem更改了,可是沒有再次執行initState方法,致使_choosedItem沒有跟着更改。因此界面就不會跟着更改。this
結論:StatefulWidget是State的配置文件,在State中直接使用StatefulWidget的屬性。spa
以上代碼改成:code
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(width: 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, ), ), ), ), ], ), ); } }