Drawer?Builder組件實現(xiàn)flutter側(cè)邊抽屜效果示例分析
前言
平時開發(fā)中難免會碰到抽屜效果,如果自己寫肯定要費一番工夫,用別人的也要付出代碼量,Scaffold
實際上已經(jīng)默認提供了 Drawer
抽屜效果供我們使用,下面我們就看看怎么使用的吧
先上一張效果圖
Drawer 與 UserAccountsDrawerHeader
Drawer
就是我們的抽屜效果,而 UserAccountsDrawerHeader
就是我們側(cè)邊欄上面的那片用戶信息頁面,可有可無,為了方便可以使用,當然也可以自己定制
下面直接上一個屬性表格,方便理解, UserAccountsDrawerHeader
從屬性就可以看到功能比較固定,可以看情況使用
Drawer屬性 | 說明 |
---|---|
elevation | 背景高度 |
child | 子組件 |
semanticLabel | 標簽 |
width | 側(cè)邊欄寬度 |
UserAccountsDrawerHeader屬性 | 說明 |
---|---|
decoration | 頭部裝飾 |
margin | 外邊距 默認8.0 |
currentAccountPicture | 主圖像 |
otherAccountsPictures | 副圖像 |
accountName | 標題 |
accountEmail | 副標題 |
onDetailsPressed | 點擊監(jiān)聽 |
話不多說,直接上代碼
Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("首頁"), ), body: const Center( child: Text("我是首頁內(nèi)容"), ), //endDrawer: Container(), //是右邊側(cè)邊欄不多說了 //我們就在這里面直接寫了,使用默認的 Drawer 就是抽屜效果了 drawer: Drawer( child: ListView( padding: const EdgeInsets.all(0), children: const <Widget>[ //側(cè)邊欄頂部效果,可以根據(jù)情況使用,可有可無 UserAccountsDrawerHeader( accountName: Text("標題"), accountEmail: Text("副標題"), //頭像 currentAccountPicture: CircleAvatar( backgroundColor: Colors.white, ), //背景 decoration: BoxDecoration(color: Colors.blue), ), ListTile(title: Text("item0..."),), ListTile(title: Text("item1..."),), ListTile(title: Text("item2..."),), ], ), ), ); }
側(cè)邊欄這樣就介紹完畢了。
讀者:這就完了?根本不夠用,感覺側(cè)邊欄按鈕跟自己的不太一樣,想換一個首頁喚出側(cè)邊欄的按鈕?
嘗試案例后,就會知道,其實上面的案例圖就是換過的側(cè)邊欄按鈕,變粗了一點,沒錯,這也和我們后面介紹的 Builder
關聯(lián)上了
定制喚出按鈕并引出 Builder 組件
實際上我們定制側(cè)邊欄的時候,只需要更換 AppBar
的 leading
即可,Scaffold
默認提供了 openDrawer
方法打開或者關閉
側(cè)邊欄,下面就距離打開側(cè)邊欄
Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("首頁"), // leading: const Leading(),//直接寫成小組件可以解決從context查找父類引起的bug leading: IconButton( onPressed: () { Scaffold.of(context).openDrawer(); //Scaffold.of(context).closeDrawer(); //關閉側(cè)邊欄 // Scaffold.of(context).openEndDrawer();//打開右側(cè)側(cè)邊欄 }, icon: const Icon(Icons.table_rows_rounded), iconSize: 20, ); ), ), body: const Center( child: Text("我是首頁內(nèi)容"), ), //我們就在這里面直接寫了 drawer: Drawer( ... ), ); }
問題
看了上面的說法和案例,那么可能會碰到一個 Bug
,就是找不到 Scaffold
,或者無法開關 Drawer
,問題在于 Scaffold.of
Scaffold.of(context)
其會像向父類查找該組件,此時我們傳遞的,context
,從哪里來的,看上面的代碼就知道,是從當前Build
中傳遞過來的 context,其祖先是誰,是我們的 MaterialApp
,因此會出現(xiàn)找不到 Scaffold
或者無法打開側(cè)邊欄的問題
//根據(jù)context到 父類祖先中查找狀態(tài) final ScaffoldState? result = context.findAncestorStateOfType<ScaffoldState>(); if (result != null) { return result; }
解決方案
外面嵌套一個 Builder
即可, Builder
實際上是一個 StatelessWidget
小組件,其就是參數(shù) builder
就是利用回調(diào)帶回了自己的 context
從而解決的 context
父類查找問題
因此,我們將 Leading
的按鈕換成一個 StatelessWidget
,也可以作為其中一個解決方案,不過,我相信很多人更愿意選擇 Builder + IconButton
,畢竟其就只有一個按鈕,這也是一些系統(tǒng)或者三方組件經(jīng)常使用 Builder
的原因了吧
Builder( builder: (context) { return IconButton( onPressed: () { //會從context的父類開始找組件context.findAncestorStateOfType //當前組件的context父組件是 MyApp 是沒有 Scaffold,且沒有drawer,因此無法打開 //Builder是一個StatelessWidget基礎組件,只不過返回了自己的context,因此沒問題 Scaffold.of(context).openDrawer(); //Scaffold.of(context).closeDrawer(); //關閉側(cè)邊欄 // Scaffold.of(context).openEndDrawer();//打開右側(cè)側(cè)邊欄 }, icon: const Icon(Icons.table_rows_rounded), iconSize: 20, ); }, ),
整體代碼
class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override State<HomePage> createState() => _HomePageState(); } //小組件 class Leading extends StatelessWidget { const Leading({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return IconButton( onPressed: () { Scaffold.of(context).openDrawer(); }, icon: const Icon(Icons.table_rows_rounded), iconSize: 20, ); } } class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("首頁"), // leading: const Leading(),//直接寫成小組件可以解決從context查找父類引起的bug leading: Builder( builder: (context) { return IconButton( onPressed: () { //會從context的父類開始找組件context.findAncestorStateOfType //當前組件的context父組件是 MyApp 是沒有 Scaffold,且沒有drawer,因此無法打開 //Builder是一個StatelessWidget基礎組件,只不過返回了自己的context,因此沒問題 Scaffold.of(context).openDrawer(); //Scaffold.of(context).closeDrawer(); //關閉側(cè)邊欄 // Scaffold.of(context).openEndDrawer();//打開右側(cè)側(cè)邊欄 }, icon: const Icon(Icons.table_rows_rounded), iconSize: 20, ); }, ), ), body: const Center( child: Text("我是首頁內(nèi)容"), ), //endDrawer: Container(), //是右邊側(cè)邊欄不多說了 //我們就在這里面直接寫了 drawer: Drawer( child: ListView( padding: const EdgeInsets.all(0), children: const <Widget>[ UserAccountsDrawerHeader( accountEmail: Text("副標題"), accountName: Text("標題"), //頭像 currentAccountPicture: CircleAvatar( backgroundColor: Colors.white, ), //背景 decoration: BoxDecoration(color: Colors.blue), ), ListTile(title: Text("item0..."),), ListTile(title: Text("item1..."),), ListTile(title: Text("item2..."),), ], ), ), ); } }
最后
快來嘗試一下吧,相信,馬上就能用個明明白白,我也是在使用其的過程中,發(fā)現(xiàn)了 Scaffold.of
查找的邏輯問題,進而進出 Builder
來解決問題,相信里面還有不少用到 Builder
的組件有類似的情況,那時候就不一定是 scaffold.of
了??
以上就是Drawer Builder組件實現(xiàn)flutter側(cè)邊抽屜效果示例分析的詳細內(nèi)容,更多關于Drawer Builder flutter側(cè)邊抽屜的資料請關注腳本之家其它相關文章!
相關文章
iOS9 系統(tǒng)分享調(diào)用之UIActivityViewController
UIActivityViewController類是一個標準的view controller,通個使用這個controller,你的應用程序就可以提供各種服務。本文給大家介紹iOS9 系統(tǒng)分享調(diào)用之UIActivityViewController,感興趣的朋友一起學習吧2015-11-11Objective-C實現(xiàn)無限循環(huán)輪播器
這篇文章主要介紹了Objective-C實現(xiàn)無限循環(huán)輪播器的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-05-05