Flutter开发2:导航栏

2022-05-04  本文已影响0人  十二栗子

底部导航栏 BottomNavigationBar

它是属于 Scaffold 中的一个位于底部的控件,与 BottomNavigationBarItem 配合使用

属性名 类型 简介
items List<BottomNavigationBarItem> 底部导航栏展示的内容项
onTap ValueChanged<int> 点击导航栏子项时的回调
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个时,则值会变为shifting,通常需要显式的将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组合使用,形成联动效果。

属性名 类型 简介
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页的内容容器,其内放置Tab页的主体内容。

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: "发展心理学",),
              Tab(text: "变态心理学",),
              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


保存状态

直接使用如上方案,在每次切换Page 页时,页面都会重新创建,initState重新执行,想要提升性能,达到我们期望的效果,则需要使用如下步骤保存状态

在State类上混入AutomaticKeepAliveClientMixin类
重写wantKeepAlive方法,并返回true
在页面的build方法中,调用super.build

iOS 风格导航栏

关于部分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("跳转新页"),
          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("新页面"),
      ),
    );
  }
}

上一篇下一篇

猜你喜欢

热点阅读