【Flutter】容器类组件之Scaffold、TabBar、底部导航
前言
一个完整的路由页可能会包含导航栏、抽屉菜单(Drawer)以及底部Tab导航菜单等。Flutter Material组件库提供了一些现成的组件来减少开发任务。Scaffold是一个路由页的骨架,使用它可以很容易地拼装出一个完整的页面。
接口描述
AppBar是一个Material风格的导航栏,通过它可以设置导航栏标题、导航栏菜单、导航栏底部的Tab标题等。
AppBar({
    Key key,
    // 导航栏最左侧的widget,常见为抽屉菜单按钮或返回按钮。可手动来设置这一项
    this.leading,
    // 如果leading为null,是否自动实现默认的leading按钮
    this.automaticallyImplyLeading = true,
    // 页面标题
    this.title,
    // 导航栏右侧菜单
    this.actions,
    this.flexibleSpace,
    // 导航栏底部菜单,通常为Tab按钮组
    this.bottom,
    // 导航栏阴影
    this.elevation,
    this.shape,
    this.backgroundColor,
    this.brightness,
    this.iconTheme,
    this.actionsIconTheme,
    this.textTheme,
    this.primary = true,
    // 标题时候居中
    this.centerTitle,
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,
    this.toolbarOpacity = 1.0,
    this.bottomOpacity = 1.0,
  }) : assert(automaticallyImplyLeading != null),
       assert(elevation == null || elevation >= 0.0),
       assert(primary != null),
       assert(titleSpacing != null),
       assert(toolbarOpacity != null),
       assert(bottomOpacity != null),
       preferredSize = Size.fromHeight(kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0)),
       super(key: key);
Material组件库中提供了一个TabBar组件,它可以快速生成Tab菜单。
const TabBar({
    Key key,
    @required this.tabs,
    this.controller,
    this.isScrollable = false,
    this.indicatorColor,
    this.indicatorWeight = 2.0,
    this.indicatorPadding = EdgeInsets.zero,
    this.indicator,
    this.indicatorSize,
    this.labelColor,
    this.labelStyle,
    this.labelPadding,
    this.unselectedLabelColor,
    this.unselectedLabelStyle,
    this.dragStartBehavior = DragStartBehavior.start,
    this.onTap,
  }) : assert(tabs != null),
       assert(isScrollable != null),
       assert(dragStartBehavior != null),
       assert(indicator != null || (indicatorWeight != null && indicatorWeight > 0.0)),
       assert(indicator != null || (indicatorPadding != null)),
       super(key: key);
Material库提供了一个TabBarView组件,通过它不仅可以轻松的实现Tab页,而且可以非常容易的配合TabBar来实现同步切换和滑动状态同步.
const TabBarView({
    Key key,
    @required this.children,
    this.controller,
    this.physics,
    this.dragStartBehavior = DragStartBehavior.start,
  }) : assert(children != null),
       assert(dragStartBehavior != null),
       super(key: key);
无论是点击导航栏Tab菜单还是在页面上左右滑动,Tab页面都会切换,并且Tab菜单的状态和Tab页面始终保持同步!那它们是如何实现同步的呢?因为TabBar和TabBarView的controller是同一个!正是如此,TabBar和TabBarView正是通过同一个controller来实现菜单切换和滑动状态同步的。
代码示例
// Scaffold、TabBar、底部导航
import 'package:flutter/material.dart';
class ScaffoldTest extends StatefulWidget {
  @override
  _ScaffoldTestState createState() => _ScaffoldTestState();
}
class _ScaffoldTestState extends State<ScaffoldTest> with SingleTickerProviderStateMixin{
  int _selectedIndex = 2;
  TabController _tabController;
  List tabs = ['会话', '系统'];
  @override
  void initState() {
    print('初始化了数据!');
    super.initState();
    // 创建Controller
    _tabController = TabController(length: tabs.length, vsync: this);
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // AppBar是一个Material风格的导航栏,通过它可以设置导航栏标题、导航栏菜单、导航栏底部的Tab标题等
      appBar: AppBar(
        // 导航栏最左侧的widget
        leading: Builder(builder: (context) {
          return IconButton(
            // 自定义图标
            icon: Icon(Icons.dashboard, color: Colors.red,),
            onPressed: () {
              // 打开抽屉菜单
              Scaffold.of(context).openDrawer();
            },
          );
        }),
        // 导航栏标题
        title: Text('Test App'),
        // 导航栏右侧菜单
        actions: <Widget>[
          IconButton(icon: Icon(Icons.share),onPressed: () {},),
        ],
        // Tab菜单
        bottom: TabBar(
          controller: this._tabController,
//          isScrollable: true,
          tabs: <Widget>[
            Tab(text: tabs[0]),
            Tab(text: tabs[1]),
          ],
        ),
      ),
      // 抽屉
      drawer: MyDrawer(),
      body: TabBarView(
        controller: this._tabController,
        children: <Widget>[
          Container(
            alignment: Alignment.center,
              child: Text(tabs[0], textScaleFactor: 10),
          ),
          Container(
            alignment: Alignment.center,
            child: Text(tabs[1], textScaleFactor: 10),
          ),
        ],
      ),
      // 底部导航
      bottomNavigationBar: BottomNavigationBar(
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页'), backgroundColor: Colors.blue,),
          BottomNavigationBarItem(icon: Icon(Icons.system_update_alt), title: Text('数据'), backgroundColor: Colors.blue,),
          BottomNavigationBarItem(icon: Icon(Icons.notifications_active), title: Text('通知'), backgroundColor: Colors.blue,),
          BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text('设置'), backgroundColor: Colors.blue,),
        ],
        currentIndex: _selectedIndex,
        fixedColor: Colors.red,
        onTap: _onItemTapped,
      ),
      // 悬浮按钮
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: _onAdd,
        backgroundColor: Colors.blue,
      ),
      // 设置悬浮按钮的位置为底部导航栏的正中间
//      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      // 增加打洞按钮
//      bottomNavigationBar: BottomAppBar(
//        color: Colors.green,
//        // 底部导航栏打一个圆形的洞
//        shape: CircularNotchedRectangle(),
//        child: Row(
//          children: <Widget>[
//            IconButton(icon: Icon(Icons.home),),
//            // 中间位置空出
//            SizedBox(),
//            IconButton(icon: Icon(Icons.business),),
//          ],
//          mainAxisAlignment: MainAxisAlignment.spaceAround,
//        ),
//      ),
    );
  }
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }
  void _onAdd() {
    print('_onAdd');
  }
}
class MyDrawer extends StatelessWidget {
  MyDrawer({Key key,}) : super(key:key);
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: MediaQuery.removePadding(
          context: context,
          // 移除抽屉菜单顶部默认留白
          removeTop: true,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.only(top: 38.0),
                child: Row(
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 16.0),
                      child: ClipOval(
                        child: Image.asset('assets/images/avatar.png', width: 80,),
                      ),
                    ),
                    Text('parzulpan',style: TextStyle(fontWeight: FontWeight.bold),)
                  ],
                ),
              ),
              Expanded(
                child: ListView(
                  children: <Widget>[
                    ListTile(
                      leading: const Icon(Icons.add),
                      title: const Text('增加账户'),
                    ),
                    ListTile(
                      leading: const Icon(Icons.info),
                      title: const Text('账户管理'),
                    ),
                  ],
                ),
              )
            ],
          )
      ),
    );
  }
}
总结
暂无
【Flutter】容器类组件之Scaffold、TabBar、底部导航的更多相关文章
- 微信小程序把玩(三)tabBar底部导航
		原文:微信小程序把玩(三)tabBar底部导航 tabBar相对而言用的还是比较多的,但是用起来并没有难,在app.json中配置下tabBar即可,注意tabBar至少需要两个最多五个Item选项 ... 
- 微信小程序tabBar底部导航 不显示问题解析
		2019年十月八号 转藏: 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/wy_Blo ... 
- 微信小程序~TabBar底部导航切换栏
		底部导航栏这个功能是非常常见的一个功能,基本上一个完成的app,都会存在一个导航栏,那么微信小程序的导航栏该怎么实现呢?经过无数的踩坑,终于实现了,好了,先看看效果图. 对于底部导航栏,小程序上给出的 ... 
- 20个Flutter实例视频教程-第02节: 底部导航栏制作-2
		视频地址: https://www.bilibili.com/video/av39709290?p=2 博客地址: https://jspang.com/post/flutterDemo.html#t ... 
- 微信小程序自定义底部导航栏组件+跳转
		微信小程序本来封装有底部导航栏,但对于想自定义样式和方法的开发者来说,这并不是很好. 参考链接:https://github.com/ljybill/miniprogram-utils/tree/ma ... 
- 【Flutter学习】基本组件之BottomNavigationBar底部导航栏
		一,概述 BottomNavigationBar即是底部导航栏控件,显示在页面底部的设计控件,用于在试图切换,底部导航栏包含多个标签.图标或者两者搭配的形式,简而言之提供了顶级视图之间的快速导航. 二 ... 
- 【Flutter学习】基本组件之TabBar顶部导航
		一,概述 TabBar,是材料设计(Material design)中很常用的一种横向标签页.在Android原生开发中,我们常用ViewPage或者一些常用的标签页开源库,来实现并行界面的横向滑动展 ... 
- Flutter——BottomNavigationBar组件(底部导航栏组件)
		BottomNavigationBar常用的属性: 属性名 说明 items List<BottomNavigationBarItem> 底部导航条按钮集合 iconSize icon c ... 
- Flutter学习笔记(17)--顶部导航TabBar、TabBarView、DefaultTabController
		如需转载,请注明出处:Flutter学习笔记(17)--顶部导航TabBar.TabBarView.DefaultTabController 上一篇我们说了BottmNavigationBar底部导航 ... 
随机推荐
- css3(::before)伪元素的使用
			1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset=" ... 
- EF 查询外键对应的实例
			EF 查询外键对应的实例 1. 查询时易遇到的情况: 能查询到外键值,但对应的外键实例为null. 解决方法: (1) 使用EF的include // 我的应用如下 // SampleResult ... 
- 写给OIer们的一些话(修订版)
			我是一个高二的OIer,离我正式退役的日子已经不超过一年了.在这个时期,与其写一些回忆性的文字,不如跳出"自我"的范畴,以一种比较全局的角度和大家一起分享一些我对OI的认知和看法. ... 
- mysql 迁移数据库到 oracle  (sql注意问题)
			http://ykdn2010.iteye.com/blog/1511349 一. 项目已用到 oracle 函数的转换 1. Oracle 中的 TO_DATE (),TO_CHAR () 示例: ... 
- activiti环境安装
			使用Eclipse安装activiti插件的时候,没有安装成功,参考这边文章才成功,链接:https://jingyan.baidu.com/article/4dc408480d4201c8d846f ... 
- eureka配置说明
			以下配置来源于jar中的源码,采用标准两个空格作为缩进 eureka.yml spring: application: name: APPLICATION_NAME # 应用名,在eureka上注册为 ... 
- Scrapy+Scrapyd+Scrapydweb实现爬虫可视化
			Scrapy+Scrapyd+Scrapydweb实现爬虫可视化 Scrapyd是一个服务,用来运行scrapy爬虫的 它允许你部署你的scrapy项目以及通过HTTP JSON的方式控制你的爬虫 官 ... 
- 看我如何用微信上线CobaltStrike
			前言 DLL劫持漏洞是老生常谈的一个漏洞,已经被前辈们各种奇技淫巧玩烂.但DLL劫持技术在后渗透和域渗透中的权限提升和权限维持都起到了至关重要的作用.本文简单剖析DLL劫持技术并通过实例应用来查看如何 ... 
- CPU的功能和基本组成结构
			目录 CPU的功能 运算器和控制器的功能 CPU的基本结构 运算器的基本结构 控制器的基本结构 整体 本节回顾 CPU的功能 指令控制:完成取指令.分析指令和执行指令的操作,即程序的顺序控制 操作控制 ... 
- 自动化管理平台rundeck的安装方法
			简介 RunDeck 是用 Java/Grails 写的开源工具,帮助用户在数据中心或者云环境中自动化各种操作和流程.通过命令行或者web界面,用户可以对任意数量的服务器进行操作,大大降低了对服务器自 ... 
