【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底部导航 ...
随机推荐
- (window)Docker的镜像使用
镜像加速 镜像默认是通过 DockerHub 拉取的,国内可能有些困难,会报以下错误: net/http: TLS handshake timeout 所以,需要配置国内的加速服务地址: 官方地址:h ...
- SseEmitter推送
后端代码SseController.java package com.theorydance.mywebsocket.server; import java.util.HashMap; import ...
- Feign使用注意事项
使用Feign时,为了不写重复代码,需要写feign公共接口方便调用,这时候需要注意以下问题,以发邮件为例 定义公共接口 /** * @author liuyalong * @date 2020/10 ...
- 使用Tomcat Native提升Tomcat IO效率
目录 简介 Tomcat的连接方式 APR和Tomcat Native 在tomcat中使用APR 简介 IO有很多种,从最开始的Block IO,到nonblocking IO,再到IO多路复用和异 ...
- Day7 python高级特性-- 切片 Slice
先举一个例子,取list或tuple中的某几个元素: 1.取 ['a','b','c','d','e','f'] 第1.2.5.6个元素: >>> a = [' ...
- rman恢复实践
1) Loss of system DATAFILE 2) Loss of non-system DATAFILE 3) Loss of a DATAFILE without Backup 4) Lo ...
- Docker(七): 安装Loki
洛基(Loki),是北欧神话中的恶作剧和谎言之神,亦是火神.他是巨人法布提(Farbauti)和女巨人劳菲(Laufey)的儿子,阿萨神族主神奥丁(Odin)的义兄弟,虽然他比奥丁要年轻许多.但他的个 ...
- ElasticSearch中head插件的简单用法
1.首先在左侧打开Query栏. 2.Query下方的第一栏是分别输入es的地址.端口号.index.type. 3.Query下方的第二栏是输入将要执行的方式,旁边的下拉框是辅助选择执行的类型,如图 ...
- 10 个 GitHub 上超火的 CSS 奇技淫巧项目,找到写 CSS 的灵感!
大家好,我是你们的 超级猫,一个不喜欢吃鱼.又不喜欢喵 的超级猫 ~ 如果 CSS 是女孩子,肯定如上图那样吧
- 用matlab提取jpg曲线数据或者jpg图片重新复原
I = imread('111.jpg');%读取处理好的图片,必须是严格坐标轴线为边界的图片 I=rgb2gray(I); %灰度变化 I(I>200)=255; %二值化 I(I<=2 ...