Flutter實(shí)戰(zhàn)--美食App(三)

鎮(zhèn)樓美女

前面一節(jié)已經(jīng)介紹完了閃屏廣告頁,那么今天要實(shí)現(xiàn)的就是HomePage界面,先來看看home界面長啥樣?如下圖所示:
home界面

  1. 底部是一個(gè)bottomNavigationBar,放置五個(gè)分類導(dǎo)航按鈕,分別對(duì)應(yīng)五個(gè)不同功能頁面;
  2. 除去底部導(dǎo)航區(qū)之外是個(gè)內(nèi)容展示區(qū),當(dāng)點(diǎn)擊底部不同的導(dǎo)航按鈕時(shí),該區(qū)域顯示不同的內(nèi)容,類似于Android原生開發(fā)的FrameLayout布局。
    接下來就一步步實(shí)現(xiàn)這個(gè)homePage頁面

lib\page目錄下新建一個(gè)home_page.dart文件,添加如下內(nèi)容:

class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with AutomaticKeepAliveClientMixin {
  //添加AutomaticKeepAliveClientMixin,
  //并實(shí)現(xiàn)對(duì)應(yīng)的方法bool get wantKeepAlive => true;
  //同時(shí)build方法實(shí)現(xiàn)父方法 super.build(context);

  @override
  Widget build(BuildContext context) {
    super.build(context);
    // 方式一:默認(rèn)設(shè)置寬度1080px,高度1920px
    ScreenUtil.init(context);
    // 方式二:設(shè)置寬度750px,高度1334px
    // ScreenUtil.init(context, width: 750, height: 1334);
    // 方式三:設(shè)置寬度750px,高度1334px,根據(jù)系統(tǒng)字體進(jìn)行縮放
    // ScreenUtil.init(context, width: 1080, height: 1920, allowFontScaling: true);
    return Scaffold(
      body: null,
 
      bottomNavigationBar: BottomNavigationBar(
        items: null,
        onTap: _onTapHandler,
        currentIndex: 0,
        type: BottomNavigationBarType.fixed,
        fixedColor: Colors.red,
        unselectedItemColor: Colors.black87,
        backgroundColor: Colors.white,
      ),
    );
  }
}

上面的代碼只是一個(gè)大概的框架。

  1. 首先在引入AutomaticKeepAliveClientMixin,這樣當(dāng)點(diǎn)擊底部導(dǎo)航按鈕切換的時(shí)候再切換回之前的頁面仍能保持頁面跳轉(zhuǎn)之前的瀏覽位置,比如說在第一個(gè)導(dǎo)航按鈕頁面瀏覽到中間的位置點(diǎn)擊了第二個(gè)導(dǎo)航按鈕切換到新頁面然后又點(diǎn)擊第一個(gè)導(dǎo)航按鈕切換回第一個(gè)頁面,這時(shí)如果不混入AutomaticKeepAliveClientMixin則第一個(gè)頁面就會(huì)重新加載,所有數(shù)據(jù)都會(huì)恢復(fù)初始狀態(tài),但是現(xiàn)在加入了這句AutomaticKeepAliveClientMixin就能保持之前的頁面瀏覽狀態(tài)而不重新加載?;烊脒@個(gè)之后要重寫其wantKeepAlive屬性,只要返回一個(gè)true即可。
 @override
  bool get wantKeepAlive => true;
  1. 同時(shí)引入第三方的屏幕適配插件flutter_screenutil: ^1.1.0,并在build方法下進(jìn)行初始化ScreenUtil.init(context),整個(gè)App的設(shè)計(jì)稿尺寸按默認(rèn)尺寸配置(1920*1080)。
  2. 添加底部導(dǎo)航按鈕對(duì)應(yīng)的page頁面,在lib\page目錄下新建五個(gè)頁面,分別命名為food_set_page.dart、food_show_page.dartfood_reviews_page.dart、heath_eat_page.dartmy_page.dart,然后在build方法中添加如下代碼:
//底部需要切換的頁面
  final List<Widget> _pages = [
    FoodSetPage(),
    FoodShowPage(),
    FoodReviewsPage(),
    HeathEatPage(),
    MyPage(),
  ];
  1. 底部的導(dǎo)航區(qū)采用的是BottomNavigationBar,其構(gòu)造方法如下,
BottomNavigationBar({
    Key key,
    @required this.items, 
    this.onTap,
    this.currentIndex = 0,
    this.elevation = 8.0,
    BottomNavigationBarType type, //
    Color fixedColor,
    this.backgroundColor,
    this.iconSize = 24.0,
    Color selectedItemColor,
    this.unselectedItemColor,
    this.selectedIconTheme = const IconThemeData(),
    this.unselectedIconTheme = const IconThemeData(),
    this.selectedFontSize = 14.0,
    this.unselectedFontSize = 12.0,
    this.selectedLabelStyle,
    this.unselectedLabelStyle,
    this.showSelectedLabels = true,
    bool showUnselectedLabels,
  })

參數(shù)說明:

屬性 說明
type 風(fēng)格BottomNavigationBarType.fixed(超過4個(gè)按鍵一定要加這個(gè),說明是多個(gè)按鈕)BottomNavigationBarType.shifting
items List<BottomNavigationBarItem>[] 底部導(dǎo)航條按鈕集合
onTap 選中變化回調(diào)函數(shù)
currentIndex 索引值,默認(rèn)0 默認(rèn)選中第幾個(gè)
elevation 默認(rèn)8
iconSize 圖片大小
BottomNavigationBarType.fixed 風(fēng)格屬性
fixedColor 選中的顏色
backgroundColor 背景顏色
BottomNavigationBarType.shifting 風(fēng)格屬性
selectedItemColor 選中時(shí)顏色
unselectedItemColor 未選中時(shí)顏色
selectedIconTheme 選中時(shí)Icon的主題
unselectedIconTheme 未選中時(shí)Icon的主題
selectedFontSize 默認(rèn)14
unselectedFontSize 默認(rèn)12
selectedLabelStyle 選中時(shí)Label的樣式
unselectedLabelStyle 未選中時(shí)Label的樣式
showSelectedLabels 默認(rèn)true
showUnselectedLabels 未選中時(shí)的Label

從上面看出,items 是必填的屬性參數(shù),也就是一個(gè) BottomNavigationBarItem Widget列表。
每個(gè)按鈕對(duì)應(yīng)一個(gè)BottomNavigationBarItem,其構(gòu)造函數(shù)如下

const BottomNavigationBarItem({
    @required this.icon,
    this.title,
    Widget activeIcon,
    this.backgroundColor,
  }) : activeIcon = activeIcon ?? icon,
       assert(icon != null);

參數(shù)說明:

屬性 說明
icon 圖標(biāo)
title 文字
activeIcon 選中后的圖標(biāo)
backgroundColor 背景色

iconactiveIcon 是兩個(gè)狀態(tài)下的圖標(biāo),title 則是文本,只有默認(rèn)的 icon 是必須的。用一個(gè)List來存放底部的導(dǎo)航item

//底部導(dǎo)航item的文字和圖片
  final List<BottomNavigationBarItem> tabs = [
    BottomNavigationBarItem(
      icon: Icon(FontAwesome.home),
      title: Text('食集'),
    ),
    BottomNavigationBarItem(
      icon: Icon(FontAwesome.gift),
      title: Text('食秀'),
    ),
    BottomNavigationBarItem(
      icon: Icon(FontAwesome.smile_o),
      title: Text('食記'),
    ),
    BottomNavigationBarItem(
      icon: Icon(FontAwesome.question_circle_o),
      title: Text('吃什么'),
    ),
    BottomNavigationBarItem(
      icon: Icon(FontAwesome.github),
      title: Text('我的'),
    ),
  ];

然后在build方法下的Scaffold中設(shè)置bottomNavigationBar的相關(guān)屬性,如下:

bottomNavigationBar: BottomNavigationBar(
        items: tabs,
        onTap: _onTapHandler,
        currentIndex: _currentIndex,
        type: BottomNavigationBarType.fixed,
        fixedColor: Colors.red,
        unselectedItemColor: Colors.black87,
        backgroundColor: Colors.white,
      ),

其中_onTapHandler是點(diǎn)擊item時(shí)觸發(fā)的回調(diào)函數(shù),

//當(dāng)前點(diǎn)擊的item
  int _currentIndex = 0;
//點(diǎn)擊底部item跳轉(zhuǎn)相應(yīng)的page
  void _onTapHandler(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
  1. Scaffoldbody屬性放置一個(gè)IndexedStack,其在同一時(shí)刻只能顯示子控件中的一個(gè)控件,通過Index屬性來設(shè)置顯示的控件。故完整的Scaffold設(shè)置如下:
 return Scaffold(
      body: IndexedStack(
        index: _currentIndex,
        children: _pages,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: tabs,
        onTap: _onTapHandler,
        currentIndex: _currentIndex,
        type: BottomNavigationBarType.fixed,
        fixedColor: Colors.red,
        unselectedItemColor: Colors.black87,
        backgroundColor: Colors.white,
      ),
    );

?傳送門 喜歡的請(qǐng)給個(gè)Star ☆

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容