Flutter實(shí)現(xiàn)底部彈窗效果
在實(shí)際開(kāi)發(fā)過(guò)程中,經(jīng)常會(huì)用到底部彈窗來(lái)進(jìn)行快捷操作,例如選擇一個(gè)選項(xiàng),選擇下一步操作等等。在 Flutter 中提供了一個(gè) showModelBottomSheet 方法用于彈出底部彈窗,本篇介紹如何使用底部彈窗。
實(shí)現(xiàn)效果
最終實(shí)現(xiàn)效果如圖片所示,分布演示了基礎(chǔ)的,全屏的和自定義的底部彈窗形式。
代碼結(jié)構(gòu)
在消息頁(yè)面 message.dart 中,使用 Column
組件構(gòu)建了三個(gè)按鈕,點(diǎn)擊每個(gè)按鈕調(diào)用不同的底部彈窗顯示。這部分代碼不展示,核心注意的方式是按鈕的 onPressed
響應(yīng)方法,需要使用 async
修飾,這是因?yàn)?ModalBottomSheet
的返回結(jié)果是一個(gè) Future
對(duì)象,需要通過(guò) await
來(lái)獲取返回結(jié)果。
onPressed: () async { int selectedIndex = await _showCustomModalBottomSheet(context, _options); print("自定義底部彈層:選中了第$selectedIndex個(gè)選項(xiàng)"); }, //...
基本使用
基本使用對(duì)于全屏和默認(rèn)只差一個(gè)參數(shù),演示代碼中,我們使用了一組模擬的數(shù)據(jù)構(gòu)建選項(xiàng)數(shù)據(jù),然后再傳給顯示底部彈窗的方法,實(shí)際這組數(shù)據(jù)大部分是從后臺(tái)獲取的。當(dāng) isScrollControlled
是 true
時(shí),則是全屏彈窗,默認(rèn)是 false
。
Future<int> _showBasicModalBottomSheet(context, List<String> options) async { return showModalBottomSheet<int>( isScrollControlled: false, context: context, builder: (BuildContext context) { return ListView.builder( itemBuilder: (BuildContext context, int index) { return ListTile( title: Text(options[index]), onTap: () { Navigator.of(context).pop(index); }); }, itemCount: options.length, ); }, ); }
需要注意的有四點(diǎn):
- 彈窗需要上下文的
context
,這是因?yàn)閷?shí)際頁(yè)面展示是通過(guò)Navigator
的push
方法導(dǎo)航的新的頁(yè)面完成的。 - 彈窗的組件構(gòu)建的
builder
方法,這里可以返回自己自定義的組件,后面的自定義組件就是在這里做文章。 - 在列表的元素的選中點(diǎn)擊事件
onTap
方法中,需要使用Navigator
的pop
方法返回上一個(gè)頁(yè)面,這里可以攜帶選中的下標(biāo)(或其他值)返回,上一個(gè)頁(yè)面可以使用await
的方式接收對(duì)應(yīng)返回的結(jié)果。 - 點(diǎn)擊蒙層也可以消失,這時(shí)候?qū)嶋H調(diào)用的方法是
Navigator.of(context).pop()
。因?yàn)闆](méi)有攜帶參數(shù),所以接收的結(jié)果是null
,需要特殊處理一下。
自定義底部彈窗
在自定義底部彈窗中,我們做了如下自定義項(xiàng):
- 彈窗的高度指定為屏幕高度的一半,這可以通過(guò)自定義組件的
Container
高度實(shí)現(xiàn)。 - 增加了標(biāo)題欄,且標(biāo)題欄有關(guān)閉按鈕:標(biāo)題在整個(gè)標(biāo)題欄是居中的,而關(guān)閉按鈕是在標(biāo)題欄右側(cè)頂部。這可以通過(guò)
Stack
堆棧布局組件實(shí)現(xiàn)不同的組件層疊及位置。 - 左上角和右上角做了圓角處理,這個(gè)可以通過(guò)
Container
的裝飾完成,但需要注意的是,由于底部彈窗默認(rèn)是有顏色的,因此要顯示出圓角需要將底部彈窗的顏色設(shè)置為透明。
自定義彈窗的代碼如下所示:
Future<int> _showCustomModalBottomSheet(context, List<String> options) async { return showModalBottomSheet<int>( backgroundColor: Colors.transparent, isScrollControlled: true, context: context, builder: (BuildContext context) { 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: [ SizedBox( height: 50, child: Stack( textDirection: TextDirection.rtl, children: [ Center( child: Text( '底部彈窗', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16.0), ), ), IconButton( icon: Icon(Icons.close), onPressed: () { Navigator.of(context).pop(); }), ], ), ), Divider(height: 1.0), Expanded( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return ListTile( title: Text(options[index]), onTap: () { Navigator.of(context).pop(index); }); }, itemCount: options.length, ), ), ]), ); }, ); }
這里有幾個(gè)額外需要注意的點(diǎn):
- 獲取屏幕的尺寸可以使用
MediaQuery.of(context).size
屬性完成。 Stack
組件根據(jù)子元素的次序依次堆疊,最后面的在最頂層。textDirection
用于排布起始位置。- 由于
Column
下面嵌套了一個(gè)ListView
,因此需要使用Expanded
將ListView
包裹起來(lái),以便有足夠的空間供ListView
的內(nèi)容區(qū)滾動(dòng),否則會(huì)報(bào)布局溢出警告。
總結(jié)
本篇介紹了三種 ModalBottomSheet 的方式, 可以看到 ModalBottomSheet 非常靈活。實(shí)際開(kāi)發(fā)過(guò)程中,還可以根據(jù)需要,利用 ModalBottomSheet的 builder 方法返回不同的組件進(jìn)而定制自己的底部彈層組件,能夠滿(mǎn)足絕大多數(shù)場(chǎng)景。同時(shí),借 ModalBottomSheet 的啟發(fā),我們自己也可以使用 Navigator方法來(lái)實(shí)現(xiàn)其他形式的彈層,例如從底部彈出登錄頁(yè),登錄后再返回原頁(yè)面。
以上所述是小編給大家介紹的Flutter實(shí)現(xiàn)底部彈窗效果,希望對(duì)大家有所幫助。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
超詳細(xì)的Android開(kāi)發(fā)調(diào)試工具ADB命令及安裝介紹
這篇文章主要介紹了Android調(diào)試工具ADB安裝使用技巧,非常詳細(xì),有需要的朋友可以借鑒參考下,希望可以有所幫助,祝大家早日升值加薪2021-09-09詳談Android中Matrix的set、pre、post的區(qū)別
下面小編就為大家?guī)?lái)一篇詳談Android中Matrix的set、pre、post的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04Android實(shí)現(xiàn)手機(jī)振動(dòng)設(shè)置的方法
這篇文章主要介紹了Android實(shí)現(xiàn)手機(jī)振動(dòng)設(shè)置的方法,涉及Android頁(yè)面布局、屬性及功能設(shè)置的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09Android 應(yīng)用Crash 后自動(dòng)重啟的方法小結(jié)
這篇文章主要介紹了Android 應(yīng)用Crash 后自動(dòng)重啟的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Flutter?繪制風(fēng)車(chē)實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Flutter?繪制風(fēng)車(chē)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android簡(jiǎn)單的利用MediaRecorder進(jìn)行錄音的實(shí)例代碼
MediaRecorder可以進(jìn)行簡(jiǎn)單的錄音,由于操作簡(jiǎn)單所以可以用來(lái)進(jìn)行基本的錄音。下面提供一個(gè)簡(jiǎn)單的例子,記得在Mainfest文件中添加權(quán)限2013-08-08Android開(kāi)發(fā)DataBinding基礎(chǔ)使用
這篇文章主要為大家介紹了Android開(kāi)發(fā)DataBinding基礎(chǔ)使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06在Android中使用WebSocket實(shí)現(xiàn)消息通信的方法詳解
這篇文章主要介紹了在Android中使用WebSocket實(shí)現(xiàn)消息通信的方法詳解,消息推送功能可以說(shuō)移動(dòng)APP不可缺少的功能之一,使用WebSocket實(shí)現(xiàn)消息推送功能。感興趣的可以了解一下2020-07-07