Flutter開發(fā)2:導航欄

底部導航欄 BottomNavigationBar

它是屬于 Scaffold 中的一個位于底部的控件,與 BottomNavigationBarItem 配合使用

屬性名 類型 簡介
items List<BottomNavigationBarItem> 底部導航欄展示的內(nèi)容項
onTap ValueChanged<int> 點擊導航欄子項時的回調(diào)
currentIndex int 當前選擇的子項索引
type BottomNavigationBarType 底部導航欄的類型,fixed、shifting兩種
selectedItemColor Color 選中時子項的顏色
unselectedItemColor Color 未選中時子項的顏色
selectedLabelStyle TextStyle 選中時子項文字的style
unselectedLabelStyle TextStyle 未選中時子項文字的style
fixedColor Color type為fixed時導航欄的顏色,默認使用ThemeData.primaryColor
iconSize double 圖標大小

需要注意,BottomNavigationBar如果不指定type,則當items小于4個時,type屬性值為fixed,大于或等于4個時,則值會變?yōu)閟hifting,通常需要顯式的將type設置為fixed以達到期望的效果

BottomNavigationBarItem 屬性

屬性名 類型 簡介
icon Widget 要顯示的圖標
title Widget 要顯示的文字
activeIcon Widget 選中時展示的icon
backgroundColor Color type為shifting時的背景顏色
 int _currentBottomBarIndex = 0;
 BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '首頁',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.park),
            label: '廣場',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.shopping_cart),
            label: '購物車',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '我的',
          )
        ],
        type: BottomNavigationBarType.fixed,
        selectedItemColor: Colors.purple,
        unselectedItemColor: Colors.grey,
        selectedFontSize: 16,
        unselectedFontSize: 14,
        currentIndex: _currentBottomBarIndex,
        selectedLabelStyle: const TextStyle(color: Colors.purple),
        unselectedLabelStyle: const TextStyle(color: Colors.grey),
        onTap: (index){
          setState(() {
            _currentBottomBarIndex = index;
          });
        },
      ),
WX20220424-113110.png

任意導航欄 TabBar

它是切換Tab頁的入口,通常會放到AppBar控件中的bottom屬性中使用,也可放到其他布局位置,其子元素按水平橫向排列布局,一般會與TabBarView組合使用,形成聯(lián)動效果。

屬性名 類型 簡介
tabs List<Widget> 要顯示的Tab列表,通常使用Tab控件
controller TabController 要顯示的文字
isScrollable bool 是否可滾動
indicatorColor Color 指示器顏色
indicatorWeight double 指示器厚度
indicatorPadding EdgeInsetsGeometry 底部指示器的Padding
indicator Decoration 指示器decoration,例如邊框等
indicatorSize TabBarIndicatorSize 指示器大小計算方式
labelColor Color 選中Tab文字顏色
labelStyle TextStyle 選中Tab文字Style
unselectedLabelColor Color 未選中Tab中文字顏色
unselectedLabelStyle TextStyle 未選中Tab中文字style

TabBar + TabBarView

TabBarView是Tab頁的內(nèi)容容器,其內(nèi)放置Tab頁的主體內(nèi)容。

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {

  @override
  void initState() {
    super.initState();
    controller = TabController(length: 4,vsync: this);
  }

  TabController controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Widget"),
        bottom: TabBar(
          controller: controller,
            tabs:[
              Tab(text: "社會心理學",),
              Tab(text: "發(fā)展心理學",),
              Tab(text: "變態(tài)心理學",),
              Tab(text: "健康心理學",)
            ]
        ),
      ),
      body: TabBarView(
        controller: controller,
        children: <Widget>[
          Icon(Icons.access_time),
          Icon(Icons.accessibility_new),
          Icon(Icons.keyboard),
          Icon(Icons.airline_seat_flat),
        ],
      ),
    );
  }
}

當我們不需要通過代碼去手動切換Tab頁時,可使用默認的控制器DefaultTabController

TabBar + PageView


保存狀態(tài)

直接使用如上方案,在每次切換Page 頁時,頁面都會重新創(chuàng)建,initState重新執(zhí)行,想要提升性能,達到我們期望的效果,則需要使用如下步驟保存狀態(tài)

在State類上混入AutomaticKeepAliveClientMixin類
重寫wantKeepAlive方法,并返回true
在頁面的build方法中,調(diào)用super.build

iOS 風格導航欄

關(guān)于部分iOS風格的控件,可以查看 Cupertino 官方文檔

Flutter 官方正在逐漸完善Cupertino風格的控件體系,但總的來說仍然存在一些問題,目前還不太建議使用,這里僅作為介紹。

CupertinoTabBar + CupertinoTabView 示例

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '頁面框架',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}


class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
      tabBar: CupertinoTabBar(
        items: const [
          BottomNavigationBarItem(label: "首頁", icon: Icon(Icons.home)),
          BottomNavigationBarItem(label: "我的", icon: Icon(Icons.account_box)),
        ],
      ),
      tabBuilder: (BuildContext context, int index) {
        return CupertinoTabView(
          builder: (context) {
            switch (index) {
              case 0:
                return const FirstPage();
                break;
              case 1:
                return const SecondPage();
                break;
              default:
                return const FirstPage();
            }
          },
        );
      },
    );
  }
}

class FirstPage extends StatefulWidget {
  const FirstPage({Key? key}) : super(key: key);

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

class _FirstPageState extends State<FirstPage> {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold (
      navigationBar: const CupertinoNavigationBar(
        middle: Text("首頁"),
        transitionBetweenRoutes: false,
      ),
      child: Center(
        child: CupertinoButton (
          child: const Text("跳轉(zhuǎn)新頁"),
          onPressed: () {
            Navigator.of(context,rootNavigator: true).push(
                CupertinoPageRoute(
                    builder: (BuildContext context) {
                      return const NewPage();
                    }
                )
            );
          },
        ),
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  const SecondPage({Key? key}) : super(key: key);

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

class _SecondPageState extends State<SecondPage> {
  @override
  Widget build(BuildContext context) {
    return const CupertinoPageScaffold (
      navigationBar: CupertinoNavigationBar(
        middle: Text("我的"),
      ),
      child: Center(
          child: Text("我的頁面")
      ),
    );
  }
}

class NewPage extends StatelessWidget {
  const NewPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        transitionBetweenRoutes: false,
      ),
      child: Container(
        alignment: Alignment.center,
        child: const Text("新頁面"),
      ),
    );
  }
}

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

相關(guān)閱讀更多精彩內(nèi)容

  • Dart 控件 https://api.flutter.dev/flutter/widgets/widgets-l...
    CodingTom閱讀 1,886評論 0 3
  • 實現(xiàn)底部導航欄并點擊切換頁面可簡述為有三種方式 TabBar + TabBarView BottomNavigat...
    DDLH閱讀 811評論 1 0
  • 在Flutter中,Widget是一切的基礎(chǔ),作為響應式渲染,屬于MVVM的實現(xiàn)機制,通過修改數(shù)據(jù),再用setSt...
    蔥花思雞蛋閱讀 1,867評論 0 4
  • Flutter里面的布局都是由各種widget組成的,所以有必要熟悉一下各種widget 基礎(chǔ) Widgets 名...
    Observer_觀者閱讀 796評論 0 3
  • 基礎(chǔ) Widgets Container : 一個擁有繪制、定位、調(diào)整大小的 widget。Row:在水平方向上排...
    吧啦吧閱讀 3,060評論 0 5

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