以下內容參考《Flutter中文開發者社區》和《Flutter實戰·第二版》,僅為個人學習、熟悉Flutter,不同版本可能有稍微不一樣。
環境
///
/// 例子來源:
/// Widgets 介紹:https://flutter.cn/docs/development/ui/widgets-intro
/// 《Flutter實戰·第二版》:https://book.flutterchina.club/chapter2/state_manage.html
///
/// 環境:
/// Flutter 3.10.1 ? channel stable ? https://github.com/flutter/flutter.git
/// Framework ? revision d3d8effc68 (7 days ago) ? 2023-05-16 17:59:05 -0700
/// Engine ? revision b4fb11214d
/// Tools ? Dart 3.0.1 ? DevTools 2.23.1
///
管理狀態的最常見的方法:
- Widget 管理自己的狀態。
- Widget 管理子 Widget 狀態。
- 混合管理(父 Widget 和子 Widget 都管理狀態)。
如何決定使用哪種管理方法?下面是官方給出的一些原則可以幫助你做決定:
- 如果狀態是用戶數據,如復選框的選中狀態、滑塊的位置,則該狀態最好由父 Widget 管理。
- 如果狀態是有關界面外觀效果的,例如顏色、動畫,那么狀態最好由 Widget 本身來管理。
- 如果某一個狀態是不同 Widget 共享的則最好由它們共同的父 Widget 管理。
Widget 管理自己的狀態
/// TapBoxA 管理自身狀態.
class TapBoxA extends StatefulWidget {
const TapBoxA({super.key});
@override
State<TapBoxA> createState() => _TapBoxAState();
}
class _TapBoxAState extends State<TapBoxA> {
bool _active = false;
void _handleTap() {
setState(() {
_active = !_active;
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Center(
child: Container(
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: _active ? Colors.lightGreen[700] : Colors.grey[600],
),
child: Center(
child: Text(
_active ? "Active" : "Inactive",
style: const TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
}
Widget 管理子 Widget 狀態。
/// ParentWidget 為 TapBoxB 管理狀態.
/// ------------------------ ParentWidget --------------------------------
class ParentWidget extends StatefulWidget {
const ParentWidget({super.key});
@override
State<ParentWidget> createState() => ParentWidgetState();
}
class ParentWidgetState extends State<ParentWidget> {
bool _active = false;
void handleTapBoxChange(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("父管理子Widget的狀態"),
backgroundColor: Colors.black,
),
body: TapBoxB(
active: _active,
onChanged: handleTapBoxChange,
),
);
}
}
///------------------------ TapBoxB ----------------------------------
class TapBoxB extends StatelessWidget {
const TapBoxB({super.key, this.active = false, required this.onChanged});
final bool active;
final ValueChanged<bool> onChanged;
void _handleTap() {
onChanged(!active);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Center(
child: Container(
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: active ? Colors.red[700] : Colors.blue[600],
),
child: Center(
child: Text(
active ? "Active" : "Inactive",
style: const TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
}
Widget 管理子 Widget 狀態
混合狀態管理
/// ------------------------ ParentWidgetC --------------------------------
class ParentWidgetC extends StatefulWidget {
const ParentWidgetC({super.key});
@override
State<ParentWidgetC> createState() => _ParentWidgetCState();
}
class _ParentWidgetCState extends State<ParentWidgetC> {
bool _activeState = false;
void _handleTabBoxChange(bool newValue) {
setState(() {
_activeState = newValue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("混合狀態管理", style: TextStyle(color: Colors.white)),
backgroundColor: Colors.blue[500],
),
body: TapBoxC(
active: _activeState,
onChanged: _handleTabBoxChange,
),
);
}
}
///----------------------------- TapBoxC ------------------------------
class TapBoxC extends StatefulWidget {
const TapBoxC({super.key, this.active = false, required this.onChanged});
final bool active;
final ValueChanged<bool> onChanged;
@override
State<TapBoxC> createState() => _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() {
setState(() {
widget.onChanged(!widget.active);
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: handleTap,
onTapDown: handleTapDown,
onTapUp: handleTapUp,
onTapCancel: handleTapCancel,
child: Center(
child: Container(
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: widget.active ? Colors.pink[200] : Colors.cyan[500],
border: highlight
? Border.all(color: Colors.orange[700]!, width: 10,)
//Border(top: BorderSide(color: Colors.orange[700]!, width: 10))
: null,
),
child: Center(
child: Text(
widget.active ? "Active" : "Inactive",
style: const TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
}
混合狀態管理