網(wǎng)站首頁 編程語言 正文
前言
前面講了Flutter布局,布局只是靜態(tài)的。在Flutter中,組件分為StatelesslWidget和StatefulWidget。
- StatelesslWidget
沒有狀態(tài),是一成不變的。比如圖標,文字,按鈕等
- StatefulWidget
有狀態(tài)的組件,頁面數(shù)據(jù)是動態(tài)的,或者會隨著用戶操作變化,比如多選框,文本輸入框等。
有狀態(tài)組件
重點來了,如何使用實現(xiàn)一個有狀態(tài)的組件呢?
- 有狀態(tài)的組件一般由兩個類構成,一個StatefulWidget子類和一個State子類.
- State類包含了組件的
build()
方法,并且負責維護組件狀態(tài) - 當這個組件的狀態(tài)變化了,可以調用
setState()
方法來刷新頁面
狀態(tài)管理
由誰來負責狀態(tài)管理呢?是組件本身,還是他的父類,兩者都有又或是其他對象?答案是都可以。也就是說有三種方法實現(xiàn)狀態(tài)管理:
1.組件自己管理自己的狀態(tài)
2.組件的父組件管理狀態(tài)
3.混搭管理
那么如何決定該用那種方式來進行狀態(tài)管理呢?一般來講有以下原則:
1.如果是用戶數(shù)據(jù),比如多選框是否被選中,一般是由選擇第2種方法
2.如果動效,比如放大縮小,那一般用第1種方法
PS:如果你實在迷芒,就直接選擇用第2種方法,用父類管理狀態(tài)。
舉例
組件自己管理自己的狀態(tài)
如下代碼:_TapboxAState
這個State
子類為TapboxA
維護狀態(tài),內部定義了一個_active
變量來決定當前是否為激活的狀態(tài),內部還定義了一個_handleTap()
回調函數(shù),來處理用戶點擊后的邏輯,并且調用了setState()
生命周期方法,重新刷新頁面。
import 'package:flutter/material.dart'; // TapboxA 自己管理狀態(tài) void main() => runApp(const MyApp()); //------------------------- TapboxA ---------------------------------- class TapboxA extends StatefulWidget { ? const TapboxA({Key? key}) : super(key: key); ? @override ? _TapboxAState 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: Container( ? ? ? ? child: Center( ? ? ? ? ? child: Text( ? ? ? ? ? ? _active ? 'Active' : 'Inactive', ? ? ? ? ? ? style: const TextStyle(fontSize: 32.0, color: Colors.white), ? ? ? ? ? ), ? ? ? ? ), ? ? ? ? width: 200.0, ? ? ? ? height: 200.0, ? ? ? ? decoration: BoxDecoration( ? ? ? ? ? color: _active ? Colors.lightGreen[700] : Colors.grey[600], ? ? ? ? ), ? ? ? ), ? ? ); ? } } //------------------------- MyApp ---------------------------------- class MyApp extends StatelessWidget { ? const MyApp({Key? key}) : super(key: key); ? @override ? Widget build(BuildContext context) { ? ? return MaterialApp( ? ? ? title: 'Flutter Demo', ? ? ? home: Scaffold( ? ? ? ? appBar: AppBar( ? ? ? ? ? title: const Text('Flutter Demo'), ? ? ? ? ), ? ? ? ? body: const Center( ? ? ? ? ? child: TapboxA(), ? ? ? ? ), ? ? ? ), ? ? ); ? } }
父組件管理狀態(tài)
更多時候我們需要父組件來決定子組件什么時候來更新狀態(tài),子組件只需要根據(jù)父組件傳過來的參數(shù)進行合理的展示即可。這種情況下子組件并不需要維護狀態(tài),所以子組件是一個StatelessWidget
,父組件ParentWidget
才是StatefulWidget
。代碼如下:
父組件維護了一個_active
變量用來標記是否為激活狀態(tài),并且實現(xiàn)了回調函數(shù)_handleTapboxChanged
用來反轉激活狀態(tài),供子組件調用。子組件TapboxB
是一個無狀態(tài)組件,只需要在被點擊的時候通知父組件來管理狀態(tài)。
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class ParentWidget extends StatefulWidget { ? const ParentWidget({Key? key}) : super(key: key); ? @override ? _ParentWidgetState createState() => _ParentWidgetState(); } class _ParentWidgetState extends State<ParentWidget> { ? bool _active = false; ? void _handleTapboxChanged(bool newValue) { ? ? setState(() { ? ? ? _active = newValue; ? ? }); ? } ? @override ? Widget build(BuildContext context) { ? ? return SizedBox( ? ? ? child: TapboxB( ? ? ? ? active: _active, ? ? ? ? onChanged: _handleTapboxChanged, ? ? ? ), ? ? ); ? } } //------------------------- TapboxB ---------------------------------- class TapboxB extends StatelessWidget { ? const TapboxB({ ? ? Key? key, ? ? this.active = false, ? ? required this.onChanged, ? }) : super(key: key); ? final bool active; ? final ValueChanged<bool> onChanged; ? void _handleTap() { ? ? onChanged(!active); ? } ? @override ? Widget build(BuildContext context) { ? ? return GestureDetector( ? ? ? onTap: _handleTap, ? ? ? child: Container( ? ? ? ? child: Center( ? ? ? ? ? child: Text( ? ? ? ? ? ? active ? 'Active' : 'Inactive', ? ? ? ? ? ? style: const TextStyle(fontSize: 32.0, color: Colors.white), ? ? ? ? ? ), ? ? ? ? ), ? ? ? ? width: 200.0, ? ? ? ? height: 200.0, ? ? ? ? decoration: BoxDecoration( ? ? ? ? ? color: active ? Colors.lightGreen[700] : Colors.grey[600], ? ? ? ? ), ? ? ? ), ? ? ); ? } } //------------------------- MyApp ---------------------------------- class MyApp extends StatelessWidget { ? const MyApp({Key? key}) : super(key: key); ? @override ? Widget build(BuildContext context) { ? ? return MaterialApp( ? ? ? title: 'Flutter Demo', ? ? ? home: Scaffold( ? ? ? ? appBar: AppBar( ? ? ? ? ? title: const Text('Flutter Demo'), ? ? ? ? ), ? ? ? ? body: const Center( // ? ? ? ? ?child: TapboxA(), ? ? ? ? ? child: ParentWidget(), ? ? ? ? ), ? ? ? ), ? ? ); ? } }
混搭管理
混搭管理狀態(tài),就是因為有些情況下我們需要父組件管理一部分狀態(tài),子組件獨立管理另一部分狀態(tài)。在本次,我們根據(jù)上例添加一個動效,按鈕按下時要顯示高亮狀態(tài)(前文講過,動效一類的狀態(tài)一般要組件本身管理),抬起時取消高亮。
如下代碼:ParentWidget
負責維護_active
狀態(tài)來標志是否被激活,子組件TapboxC
負責維護_highlight
狀態(tài)用來控制是否高亮顯示。
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class ParentWidget extends StatefulWidget { ? const ParentWidget({Key? key}) : super(key: key); ? @override ? _ParentWidgetState createState() => _ParentWidgetState(); } class _ParentWidgetState extends State<ParentWidget> { ? bool _active = false; ? void _handleTapboxChanged(bool newValue) { ? ? setState(() { ? ? ? _active = newValue; ? ? }); ? } ? @override ? Widget build(BuildContext context) { ? ? return SizedBox( ? ? ? child: TapboxC( ? ? ? ? active: _active, ? ? ? ? onChanged: _handleTapboxChanged, ? ? ? ), ? ? ); ? } } //----------------------------- TapboxC ------------------------------ class TapboxC extends StatefulWidget { ? const TapboxC({ ? ? Key? key, ? ? this.active = false, ? ? required this.onChanged, ? }) : super(key: key); ? final bool active; ? final ValueChanged<bool> onChanged; ? @override ? _TapboxCState 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() { ? ? widget.onChanged(!widget.active); ? } ? @override ? Widget build(BuildContext context) { ? ? return GestureDetector( ? ? ? onTapDown: _handleTapDown, // Handle the tap events in the order that ? ? ? onTapUp: _handleTapUp, // they occur: down, up, tap, cancel ? ? ? onTap: _handleTap, ? ? ? onTapCancel: _handleTapCancel, ? ? ? child: Container( ? ? ? ? child: Center( ? ? ? ? ? child: Text(widget.active ? 'Active' : 'Inactive', ? ? ? ? ? ? ? style: const TextStyle(fontSize: 32.0, color: Colors.white)), ? ? ? ? ), ? ? ? ? width: 200.0, ? ? ? ? height: 200.0, ? ? ? ? decoration: BoxDecoration( ? ? ? ? ? color: _highlight?Colors.lightGreen :widget.active ? Colors.lightGreen[700] : Colors.grey[600], ? ? ? ? ), ? ? ? ), ? ? ); ? } } //------------------------- MyApp ---------------------------------- class MyApp extends StatelessWidget { ? const MyApp({Key? key}) : super(key: key); ? @override ? Widget build(BuildContext context) { ? ? return MaterialApp( ? ? ? title: 'Flutter Demo', ? ? ? home: Scaffold( ? ? ? ? appBar: AppBar( ? ? ? ? ? title: const Text('Flutter Demo'), ? ? ? ? ), ? ? ? ? body: const Center( // ? ? ? ? ?child: TapboxA(), ? ? ? ? ? child: ParentWidget(), ? ? ? ? ), ? ? ? ), ? ? ); ? } }
當然你也可以把高亮顯示的狀態(tài)交給父組件來管理,但是當你開發(fā)完這個組件交給同事來用的時候,別人可能只會關注業(yè)務邏輯上的處理,不會關注的動效處理。
其他交互組件
Flutter內部預置了很多交互組件,甚至還有IOS風格的組件,都可以拿來用。如果有必要的話,可以向上面的例子一樣自定義組件使用。
原文鏈接:https://blog.csdn.net/qq_18454025/article/details/121613418
相關推薦
- 2023-01-17 Linux?ps命令詳解及Linux查看進程的操作方法_linux shell
- 2022-12-27 flutter?text組件使用示例詳解_Android
- 2022-04-09 數(shù)據(jù)庫連接池Driud使用JbbcUtils工具包
- 2024-01-16 ignore_above 解決keyword字段超長
- 2022-09-09 Redis中ZSet的具體使用_Redis
- 2023-01-18 Python函數(shù)的參數(shù)列表解析_python
- 2022-09-22 string類的模擬實現(xiàn)
- 2022-07-17 SQL?Server格式轉換函數(shù)Cast、Convert介紹_MsSql
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支