Flutter 構(gòu)建一個常用的頁面框架
最終實(shí)現(xiàn)的結(jié)果如上圖所示,頂部共用一個導(dǎo)航欄,底部有四個圖標(biāo)導(dǎo)航,點(diǎn)擊對應(yīng)的圖標(biāo)跳轉(zhuǎn)到對應(yīng)的頁面。
圖標(biāo)準(zhǔn)備
本次例程需要4個圖標(biāo),2種顏色,可以從 iconfont 中找到自己需要的圖標(biāo)下載不同的顏色使用。然后在 pubspec.yaml 中的 assets 指定素材所在目錄。需要注意的是如果是 png 文件直接指定整個目錄即可,但如果是 jpg 格式,則需要同時指定文件名及后綴。
BottomNavigationBar 簡介
BottomNavigationBar的構(gòu)造函數(shù)如下:
BottomNavigationBar({ Key? key, required this.items, this.onTap, this.currentIndex = 0, this.elevation, this.type, Color? fixedColor, this.backgroundColor, this.iconSize = 24.0, Color? selectedItemColor, this.unselectedItemColor, this.selectedIconTheme, this.unselectedIconTheme, this.selectedFontSize = 14.0, this.unselectedFontSize = 12.0, this.selectedLabelStyle, this.unselectedLabelStyle, this.showSelectedLabels, this.showUnselectedLabels, this.mouseCursor, })
其中常用的屬性為:
- items:及對應(yīng)的頁面組件數(shù)組
- currentIndex:默認(rèn)顯示第幾個頁面
- type:組件類型,使用BottomNavigationBarType枚舉,有 fixed 和 shifting 兩種。fixed 是圖標(biāo)固定位置,而 shifting 的圖標(biāo)點(diǎn)擊后會有一個漂移效果,可以實(shí)際試一下,一般用fixed 比較多。
- onTap:點(diǎn)擊后的事件,一般用這個更新狀態(tài)數(shù)據(jù),以便更新頁面。
其他屬性用于控制樣式的,可以根據(jù)實(shí)際需要設(shè)置圖標(biāo)大小,主題色,字體等參數(shù)。
構(gòu)建項(xiàng)目頁面結(jié)構(gòu)
首先,新建四個業(yè)務(wù)頁面,分別是 dynamic.dart,message.dart,category.dart 和 mine.dart,分別對應(yīng)動態(tài)、消息、分類瀏覽和個人中心四個頁面。目前這四個頁面很簡單,只是在頁面中間依次顯示“島上碼農(nóng)”四個字。代碼都是類似的,以 dynamic 為例:
import 'package:flutter/material.dart'; class DynamicPage extends StatelessWidget { const DynamicPage({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text('島'), ), ); } }
注意的是這里的 Scaffold 沒有 AppBar 了,這是因?yàn)樵谑醉撘呀?jīng)有了,如果再有 AppBar 就會出現(xiàn)兩個。
其次,新建首頁,用于管理四個業(yè)務(wù)頁面,命名為 app.dart。app.dart 使用了 BottomNavigationBar 管理四個業(yè)務(wù)頁面的切換。
import 'package:flutter/material.dart'; import 'dynamic.dart'; import 'message.dart'; import 'category.dart'; import 'mine.dart'; class AppHomePage extends StatefulWidget { AppHomePage({Key key}) : super(key: key); @override _AppHomePageState createState() => _AppHomePageState(); } class _AppHomePageState extends State<AppHomePage> { int _index = 0; List<Widget> _homeWidgets = [ DynamicPage(), MessagePage(), CategoryPage(), MinePage(), ]; void _onBottomNagigationBarTapped(index) { setState(() { _index = index; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('島上碼農(nóng)'), ), body: IndexedStack( index: _index, children: _homeWidgets, ), bottomNavigationBar: BottomNavigationBar( type: BottomNavigationBarType.fixed, currentIndex: _index, onTap: _onBottomNagigationBarTapped, items: [ _getBottomNavItem( '動態(tài)', 'images/dynamic.png', 'images/dynamic-hover.png', 0), _getBottomNavItem( ' 消息', 'images/message.png', 'images/message-hover.png', 1), _getBottomNavItem( '分類瀏覽', 'images/category.png', 'images/category-hover.png', 2), _getBottomNavItem( '個人中心', 'images/mine.png', 'images/mine-hover.png', 3), ], ), ); } BottomNavigationBarItem _getBottomNavItem( String title, String normalIcon, String pressedIcon, int index) { return BottomNavigationBarItem( icon: _index == index ? Image.asset( pressedIcon, width: 32, height: 28, ) : Image.asset( normalIcon, width: 32, height: 28, ), label: title, ); } }
這里關(guān)鍵的地方有兩個,一是使用的 IndexedStack,這是一個管理頁面顯示層級的容器。使用 index 屬性確定當(dāng)前容器里那個頁面在最頂上,容器里的頁面通過 children 屬性設(shè)置,要求是一個 Widget 數(shù)組。因此,邏輯就是當(dāng) BottomNavigationBar 中的圖標(biāo)被點(diǎn)擊后,對應(yīng)點(diǎn)擊事件會回調(diào) onTap屬性指定的方法,將當(dāng)前的點(diǎn)擊索引值傳遞回調(diào)函數(shù),因此可以利用這個方式控制 IndexedStack 的頁面層級切換。
最后,使用了狀態(tài)變量_index 存儲IndexedStatck當(dāng)前顯示頁面的索引值,然后當(dāng) BottomNavigationBar的圖標(biāo)點(diǎn)擊事件發(fā)生后,在回調(diào)函數(shù)中使用 setState 更新狀態(tài)變量_index 來刷新當(dāng)前界面。
簡化入口
main.dart 是入口文件,應(yīng)當(dāng)做最基礎(chǔ)的配置和全局初始化配置,而不應(yīng)該有業(yè)務(wù)代碼,因此可以簡化為從main 方法加載首頁即可。通過這種方式可以讓 main.dart 文件即為簡潔。這也是在開發(fā)的時候需要注意的地方,將不相關(guān)的代碼剝離,相關(guān)的代碼聚合,即所謂的“高內(nèi)聚,低耦合”原則。
import 'package:flutter/material.dart'; import 'app.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'App 框架', theme: ThemeData( primarySwatch: Colors.blue, ), home: AppHomePage(), ); } }
代碼復(fù)用
寫代碼的時候要注意復(fù)用,在這里將構(gòu)建 BottomNavigationBar 元素抽離出了一個構(gòu)建方法_getBottomNavItem,從而提高代碼的復(fù)用性和維護(hù)性,也可以避免 Flutter 的組件構(gòu)建的 build 方法中出現(xiàn)過多的元素和嵌套,影響代碼的可讀性。
以上就是Flutter 構(gòu)建一個常用的頁面框架的詳細(xì)內(nèi)容,更多關(guān)于Flutter 構(gòu)建頁面框架的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android通知欄微技巧一些需要注意的小細(xì)節(jié)
這篇文章主要介紹了Android通知欄微技巧,那些你所沒關(guān)注過的小細(xì)節(jié),小編把此文分享到腳本之家平臺,需要的朋友可以參考下2018-04-04kotlin實(shí)現(xiàn)快遞與號碼歸屬地查詢案例詳解
時間軸時一個很炫酷的效果,一般作用在物流信息上,我們同樣也可以作為一個學(xué)習(xí)對象去學(xué)習(xí)他的使用方法,同時呢,我們可以在線查詢我們的電話號碼歸屬地,巧用鍵盤的邏輯提升我們用戶體驗(yàn)2023-02-02Android AlertDialog六種創(chuàng)建方式案例詳解
這篇文章主要介紹了Android AlertDialog六種創(chuàng)建方式案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08ListView的View回收引起的checkbox狀態(tài)改變監(jiān)聽等問題解決方案
之前講到了自定義Adapter傳遞給ListView時,因?yàn)長istView的View回收,需要注意當(dāng)ListView列表項(xiàng)中包含有帶有狀態(tài)標(biāo)識控件的問題,感興趣的朋友可以祥看本文,或許會有意外的收獲哦2013-01-01Android字體大小自適應(yīng)不同分辨率的解決辦法
這篇文章主要介紹了Android字體大小自適應(yīng)不同分辨率的解決辦法的相關(guān)資料,需要的朋友可以參考下2017-06-06