widget管理狀態的三種方式
阿新 • • 發佈:2020-07-22
1.自身管理自己
_TapboxAState 類:
- 管理TapboxA的狀態。
- 定義
_active
:確定盒子的當前顏色的布林值。 - 定義
_handleTap()
函式,該函式在點選該盒子時更新_active
,並呼叫setState()
更新UI。 - 實現widget的所有互動式行為。
// TapboxA 管理自身狀態.
//------------------------- TapboxA ----------------------------------
class TapboxA extends StatefulWidget {
TapboxA({Key key}) : super(key: key);
2.父類管理自己
栗子:
在以下示例中,TapboxB通過回撥將其狀態匯出到其父元件,狀態由父元件管理,因此它的父元件為StatefulWidget
。但是由於TapboxB不管理任何狀態,所以TapboxB
為StatelessWidget
。
ParentWidgetState
類:
- 為TapboxB 管理
_active
狀態。 - 實現
_handleTapboxChanged()
,當盒子被點選時呼叫的方法。 - 當狀態改變時,呼叫
setState()
更新UI。
TapboxB 類:
- 繼承
StatelessWidget
類,因為所有狀態都由其父元件處理。 - 當檢測到點選時,它會通知父元件。
// ParentWidget 為 TapboxB 管理狀態.//------------------------ ParentWidget -------------------------------- class ParentWidget extends StatefulWidget { @override _ParentWidgetState createState()=> new _ParentWidgetState(); } class _ParentWidgetState extends State<ParentWidget> { bool _active = false; void _handleTapboxChanged(bool newValue) { setState(() { _active = newValue; }); } @override Widget build(BuildContext context) { return new Container( child: new TapboxB( active: _active, onChanged: _handleTapboxChanged, ), ); } } //------------------------- TapboxB ---------------------------------- class TapboxB extends StatelessWidget { TapboxB({Key key, this.active: false, @required this.onChanged}) : super(key: key); final bool active; final ValueChanged<bool> onChanged; //回撥函式 void _handleTap() { onChanged(!active); } Widget build(BuildContext context) { return new GestureDetector( onTap: _handleTap, child: new Container( child: new Center( child: new Text( active ? 'Active' : 'Inactive', style: new TextStyle(fontSize: 32.0, color: Colors.white), ), ), width: 200.0, height: 200.0, decoration: new BoxDecoration( color: active ? Colors.lightGreen[700] : Colors.grey[600], ), ), ); } }
再加上主app的程式碼,將home頁設為ParentWidget:
void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp(//程式主體Material App c title: 'Flutter Demo', initialRoute: "/", theme: new ThemeData( primarySwatch: Colors.blue, ), //註冊路由表 routes:{ //"new_page":(context) => NewRoute(), //"new_page":(context) => EchoRoute(), //"/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //註冊首頁路由 //"Counter":(context) => CounterWidget(), }, //home: new MyHomePage(title: 'Flutter Demo Home Page'), home:ParentWidget(), ); } }
執行截圖如下:
3.
混合狀態管理
//---------------------------- ParentWidget ---------------------------- class ParentWidgetC extends StatefulWidget { @override _ParentWidgetCState createState() => new _ParentWidgetCState(); } class _ParentWidgetCState extends State<ParentWidgetC> { bool _active = false; //這裡儲存實際tapboxC是否啟用的bool值 void _handleTapboxChanged(bool newValue) {//更改tapboxC啟用狀態時回撥的函式 setState(() { _active = newValue; }); } @override Widget build(BuildContext context) {//父類widget的build函式:生成一個容器,裡面有一個tapboxC,該盒子的active用父類的_active初始化(false) print("_parentWidgetCState Build"); //onChanged屬性指明為父類中的_handleTapboxChanged,即盒子的active是由父類控制的 return new Container( child: new TapboxC( active: _active, onChanged: _handleTapboxChanged, ), ); } } //----------------------------- TapboxC ------------------------------ class TapboxC extends StatefulWidget { TapboxC({Key key, this.active: false, @required this.onChanged}) : super(key: key); final bool active; final ValueChanged<bool> onChanged; @override _TapboxCState createState() => new _TapboxCState(); }
//TapboxCState類
class _TapboxCState extends State<TapboxC> { bool _highlight = false;//盒子是否高亮 void _handleTapDown(TapDownDetails details) {//處理按下 setState(() { _highlight = true; }); } void _handleTapUp(TapUpDetails details) {//處理滑鼠抬起 setState(() { _highlight = false; }); } void _handleTapCancel() { //處理不會造成點選的按下取消 setState(() { _highlight = false; }); } void _handleTap() { widget.onChanged(!widget.active); } @override Widget build(BuildContext context) { // 在按下時新增綠色邊框,當抬起時,取消高亮 return new GestureDetector( onTapDown: _handleTapDown, // 處理按下事件 onTapUp: _handleTapUp, // 處理抬起事件 onTap: _handleTap, //處理按下取消 onTapCancel: _handleTapCancel, child: new Container( child: new Center( child: new Text(widget.active ? 'Active' : 'Inactive', style: new TextStyle(fontSize: 32.0, color: Colors.white)), ), width: 200.0, height: 200.0, decoration: new BoxDecoration(//按下螢幕出現的四周邊框 color: widget.active ? Colors.lightGreen[700] : Colors.grey[600], border: _highlight ? new Border.all( color: Colors.teal[700], width: 10.0, ) : null, ), ), ); } }