Flutter多項(xiàng)選擇彈窗實(shí)現(xiàn)詳解
在Flutter 底部彈窗詳解一篇中介紹了底部彈窗的實(shí)現(xiàn)。發(fā)出后有在琢磨如何實(shí)現(xiàn)多選,這也是很常用的一個(gè)功能。本篇介紹實(shí)現(xiàn)多選的思路和實(shí)現(xiàn)方式。
多選和單選的不同之處
單選的時(shí)候,選中一個(gè)就可以直接把結(jié)果返回,因此本身底部彈窗無需狀態(tài)管理。但到多選的時(shí)候,需要知道當(dāng)前選中的選項(xiàng),有選項(xiàng)被點(diǎn)擊的時(shí)候需要存儲(chǔ)下來,當(dāng)再次被點(diǎn)擊的時(shí)候要清空這個(gè)選項(xiàng),同時(shí)界面還需要同步更新,因此就涉及到狀態(tài)管理了。
實(shí)現(xiàn)方式
在Flutter 中提供了一個(gè) StatefulBuilder
的類,提供了一個(gè) builder
方法構(gòu)建有狀態(tài)組件,并且提供了狀態(tài)更新方法,因此在里面完成狀態(tài)管理。
StatefulBuilder(builder: (context1, setState) { return Widget; } )
在這個(gè) builder
方法中,setState
其實(shí)就是對(duì)應(yīng)狀態(tài)組件的setState
對(duì)應(yīng)的方法,這個(gè) state 就是用于控制 StatefulBuilder
生成的組件的狀態(tài)的。這種方式有點(diǎn)類似于 React
的 useState
的鉤子函數(shù)用法。
界面變更
首先底部彈窗的頭部組件要更換,需要增加確認(rèn)按鈕,將構(gòu)建該組件的方法抽離出來如下所示:
Widget _getModalSheetHeaderWithConfirm(String title, {Function onCancel, Function onConfirm}) { return SizedBox( height: 50, child: Row( children: [ IconButton( icon: Icon(Icons.close), onPressed: () { onCancel(); }, ), Expanded( child: Center( child: Text( title, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0), ), ), ), IconButton( icon: Icon( Icons.check, color: Colors.blue, ), onPressed: () { onConfirm(); }), ], ), ); }
通過這個(gè)方法可以通過外部參數(shù)傳入標(biāo)題,取消響應(yīng)事件回調(diào)和確認(rèn)事件回調(diào),通用性更強(qiáng)。
其次是選項(xiàng)需要有圖標(biāo)標(biāo)記,選中時(shí)顯示為勾選框,未選中時(shí)是空白框,這需要通過狀態(tài)數(shù)據(jù)來控制。這里我們使用了 Set
類型,保證選中的數(shù)據(jù)集是不重復(fù)的。在點(diǎn)擊選項(xiàng)時(shí),如果選項(xiàng)對(duì)應(yīng)數(shù)組的下標(biāo)在 Set
內(nèi),則從中移出,表示取消選擇;如果不在 Set
內(nèi),則加入其中,表示選中。這個(gè)過程需要包在 state
里,以更新界面。通過列表元素當(dāng)前的下標(biāo)是否在 Set
內(nèi),如果在則顯示為選中,不在則顯示未選中。
最后是確認(rèn)事件的回調(diào),確認(rèn)后將 Set
的元素轉(zhuǎn)換為數(shù)組返回,然后供上級(jí)業(yè)務(wù)使用選中的下標(biāo)數(shù)組判斷選擇了那些數(shù)據(jù)。
代碼實(shí)現(xiàn)
關(guān)鍵代碼實(shí)現(xiàn)如下,重點(diǎn)關(guān)注一下StatefulBuilder
的使用和利用 Set
這一數(shù)據(jù)類型對(duì)應(yīng)的選擇和取消選擇的操作業(yè)務(wù)邏輯。
Future<List<int>> _showMultiChoiceModalBottomSheet( BuildContext context, List<String> options) async { Set<int> selected = Set<int>(); return showModalBottomSheet<List<int>>( backgroundColor: Colors.transparent, isScrollControlled: true, context: context, builder: (BuildContext context) { return StatefulBuilder(builder: (context1, setState) { return Container( clipBehavior: Clip.antiAlias, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: const Radius.circular(20.0), topRight: const Radius.circular(20.0), ), ), height: MediaQuery.of(context).size.height / 2.0, child: Column(children: [ _getModalSheetHeaderWithConfirm('多選底部彈窗', onCancel: () { Navigator.of(context).pop(); }, onConfirm: () { Navigator.of(context).pop(selected.toList()); }, ), Divider(height: 1.0), Expanded( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return ListTile( trailing: Icon( selected.contains(index) ? Icons.check_box : Icons.check_box_outline_blank, color: Theme.of(context).primaryColor), title: Text(options[index]), onTap: () { setState(() { if (selected.contains(index)) { selected.remove(index); } else { selected.add(index); } }); }, ); }, itemCount: options.length, ), ), ]), ); }); }, ); }
總結(jié)
本篇介紹了底部彈窗實(shí)現(xiàn)多選的方式,其中實(shí)現(xiàn)的方式還可以有很多種,例如直接在自定義組件中使用有狀態(tài)組件。這里介紹的方法可以作為一個(gè)參考,通過動(dòng)態(tài)構(gòu)建有狀態(tài)組件能夠簡單快速地實(shí)現(xiàn)底部彈窗的多選功能。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android多媒體應(yīng)用使用MediaPlayer播放音頻
這篇文章主要為大家詳細(xì)介紹了Android多媒體應(yīng)用使用MediaPlayer播放音頻,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Android開發(fā)筆記之:消息循環(huán)與Looper的詳解
本篇文章是對(duì)Android中消息循環(huán)與Looper的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05清楚詳解Android?進(jìn)程間圖傳遞圖形buffer原理
這篇文章主要為大家清楚的詳解了Android?進(jìn)程間圖傳遞圖形buffer原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Flutter應(yīng)用集成極光推送的實(shí)現(xiàn)示例
這篇文章主要介紹了Flutter應(yīng)用集成極光推送的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02Android 獲取IP地址的實(shí)現(xiàn)方法
這篇文章主要介紹了Android 獲取IP地址的實(shí)現(xiàn)方法的相關(guān)資料,這里提供了具體實(shí)現(xiàn)的方法及代碼,使用WIFI 和GPRS的思路,需要的朋友可以參考下2016-11-11Android?DataBinding類關(guān)系深入探究
看了谷歌官方文章確實(shí)寫的太簡略了,甚至看完之后有很多地方還不知道怎么回事兒或者怎么用,那么接下來我將通過文章全面介紹一下DataBinding類關(guān)系2022-11-11Android編程實(shí)現(xiàn)禁止系統(tǒng)鎖屏與解鎖亮屏的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)禁止系統(tǒng)鎖屏與解鎖亮屏的方法,實(shí)例分析了Android關(guān)閉屏幕、鎖屏及解鎖屏幕的相關(guān)技巧,需要的朋友可以參考下2015-12-12