Flutter多項(xiàng)選擇彈窗實(shí)現(xiàn)詳解
在Flutter 底部彈窗詳解一篇中介紹了底部彈窗的實(shí)現(xiàn)。發(fā)出后有在琢磨如何實(shí)現(xiàn)多選,這也是很常用的一個(gè)功能。本篇介紹實(shí)現(xiàn)多選的思路和實(shí)現(xiàn)方式。

多選和單選的不同之處
單選的時(shí)候,選中一個(gè)就可以直接把結(jié)果返回,因此本身底部彈窗無(wú)需狀態(tài)管理。但到多選的時(shí)候,需要知道當(dāng)前選中的選項(xiàng),有選項(xiàng)被點(diǎn)擊的時(shí)候需要存儲(chǔ)下來(lái),當(dāng)再次被點(diǎn)擊的時(shí)候要清空這個(gè)選項(xiàng),同時(shí)界面還需要同步更新,因此就涉及到狀態(tài)管理了。
實(shí)現(xiàn)方式
在Flutter 中提供了一個(gè) StatefulBuilder 的類(lèi),提供了一個(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)類(lèi)似于 React 的 useState 的鉤子函數(shù)用法。
界面變更
首先底部彈窗的頭部組件要更換,需要增加確認(rèn)按鈕,將構(gòu)建該組件的方法抽離出來(lái)如下所示:
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();
}),
],
),
);
}
通過(guò)這個(gè)方法可以通過(guò)外部參數(shù)傳入標(biāo)題,取消響應(yīng)事件回調(diào)和確認(rèn)事件回調(diào),通用性更強(qiáng)。
其次是選項(xiàng)需要有圖標(biāo)標(biāo)記,選中時(shí)顯示為勾選框,未選中時(shí)是空白框,這需要通過(guò)狀態(tài)數(shù)據(jù)來(lái)控制。這里我們使用了 Set類(lèi)型,保證選中的數(shù)據(jù)集是不重復(fù)的。在點(diǎn)擊選項(xiàng)時(shí),如果選項(xiàng)對(duì)應(yīng)數(shù)組的下標(biāo)在 Set內(nèi),則從中移出,表示取消選擇;如果不在 Set內(nèi),則加入其中,表示選中。這個(gè)過(guò)程需要包在 state里,以更新界面。通過(guò)列表元素當(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ù)類(lèi)型對(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è)參考,通過(guò)動(dòng)態(tài)構(gòu)建有狀態(tài)組件能夠簡(jiǎn)單快速地實(shí)現(xiàn)底部彈窗的多選功能。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android使用RollViewPager實(shí)現(xiàn)輪播圖
這篇文章主要為大家詳細(xì)介紹了Android使用RollViewPager實(shí)現(xiàn)輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
一款A(yù)ndroid APK的結(jié)構(gòu)構(gòu)成解析
本篇文章介紹了我在學(xué)習(xí)過(guò)程中對(duì)于Android 程序的理解總結(jié),刨析了apk的組成與產(chǎn)生過(guò)程,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下2021-10-10
ListView實(shí)現(xiàn)聊天列表之處理不同數(shù)據(jù)項(xiàng)
這篇文章主要為大家詳細(xì)介紹了ListView實(shí)現(xiàn)聊天列表之處理不同數(shù)據(jù)項(xiàng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Android指紋識(shí)別認(rèn)識(shí)和基本使用詳解
這篇文章主要為大家詳細(xì)介紹了Android指紋識(shí)別認(rèn)識(shí)和基本的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Android手勢(shì)密碼實(shí)現(xiàn)實(shí)例代碼
本篇文章主要介紹了Android手勢(shì)密碼實(shí)現(xiàn)實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android 在viewPager中雙指縮放圖片雙擊縮放圖片單指拖拽圖片的實(shí)現(xiàn)思路
本文通過(guò)實(shí)例代碼給大家講解了Android 在viewPager中雙指縮放圖片雙擊縮放圖片單指拖拽圖片的實(shí)現(xiàn)思路及解決方案,需要的朋友參考下吧2017-05-05
Android?Flutter實(shí)現(xiàn)有趣的頁(yè)面滾動(dòng)效果
Flutter提供了?CustomScrollView?來(lái)粘合多個(gè)滑動(dòng)組件,并且可以實(shí)現(xiàn)更有趣的滑動(dòng)效果,本文就來(lái)為大家詳細(xì)講講實(shí)現(xiàn)的方法,需要的可以參考一下2022-06-06

