Flutter-Widget管理状态的三种方式
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, ), ), ); } }
进击的小🐴农