Futter基础11篇: 实现自定义AppBar 定义顶部Tab切换、底部Tab结合顶部Tab实现类似头条页面布局
效果图:
Home.dart
AppBarDemo.dart
Categroy.dart
底部导航基本架构参考:flutter实现底部导航
main.dart
import 'package:flutter/material.dart';import 'routes/Routes.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget{@overrideWidget build(BuildContext context) {// TODO: implement buildreturn MaterialApp(debugShowCheckedModeBanner: false, //去掉debug图标initialRoute: '/', //初始化的时候加载的路由
// home: Tabs(), //将代码全部抽离出去成一个Tabs组件,再抽离成一个初始化路由组件,在上方 initialRoute: '/',//配置命名路由onGenerateRoute: oonGenerateRoute //将抽离出去的路由传值规范赋值给左边,而不是执行,记住喔!);}
}
Routes.dart
import '../pages/Tabs.dart';import 'package:flutter/material.dart';import '../pages/AppBarDemo.dart';//配置路由
final routes={ //配置命名路由'/':(context)=>Tabs(), //命名路由传值 arguments工具是必须的'/appBarDemo':(context)=>AppBarDemoPage()
};//固定写法
var oonGenerateRoute=(RouteSettings settings) {// 统一处理final String name = settings.name; //得到命名路由的名字,例如:'/form'final Function pageContentBuilder = routes[name]; //得到命名路由的键去获取值,例如:(context)=>FormPage(),if (pageContentBuilder != null) {if (settings.arguments != null) {final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context, arguments: settings.arguments));return route;} else {final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context));return route;}}
};
Tabs.dart
import 'package:flutter/material.dart';
import 'tabs/Category.dart';
import 'tabs/Home.dart';
import 'tabs/Setting.dart';class Tabs extends StatefulWidget {final index; //用来作为返回根路由时,判断要显示第几个底部导航项的坐标Tabs({Key key,this.index=0}) : super(key: key); //可选参数,默认是0@override_TabsState createState() => _TabsState(this.index); //把当前坐标通过_TabsState构造方法传给_TabsState类
}class _TabsState extends State<Tabs> {int _currentIndex;_TabsState(index){ //接收Tabs 类调用时,传过来的参数,赋值给 _currentIndexthis._currentIndex=index;}List _pageList = [ //先将所有页面放到List集合内HomePage(),CategoryPage(),SettingPage()];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('FlutterDemo'),),body: this._pageList[this._currentIndex], //再根据下标获取对应页面设置到body 里bottomNavigationBar: BottomNavigationBar( //自定义底部导航条currentIndex: this._currentIndex, //配置对应的索引值选中onTap: (int index){setState(() { //改变状态this._currentIndex=index; //更改选中的Tab坐标});},
// iconSize: 45.0, //Icon的大小,默认在20左右fixedColor: Colors.red, //选中的颜色,默认是蓝色items:[BottomNavigationBarItem( //设置导航项icon:Icon(Icons.home),title: Text('首页')),BottomNavigationBarItem( //设置导航项icon:Icon(Icons.category),title: Text('分类')),BottomNavigationBarItem( //设置导航项icon:Icon(Icons.settings),title: Text('设置'))]),);}
}
AppBarDemo.dart
import 'package:flutter/material.dart';class AppBarDemoPage extends StatelessWidget {@overrideWidget build(BuildContext context) {return DefaultTabController( //顶部导航切换length: 2, //必须配置:顶部图标一共多少个child: Scaffold(appBar: AppBar(title: Text('AppBarDemoPage'),backgroundColor: Colors.red, //设置导航上的背景颜色centerTitle: true, //设置:无论是在Android 还是 ios 上,标题都是居中显示
// leading: Icon(Icons.menu), //给导航左边添加图标,默认是返回图标,无法监听
// leading: IconButton(
// icon: Icon(Icons.menu), //给导航左边添加图标,默认是返回图标,可以监听
// onPressed: (){// print('menu');
// },
// ),
// actions: <Widget>[ //右侧添加图标按钮
// IconButton(
// icon: Icon(Icons.search),
// onPressed: (){// print('search');
// },
// ),
// IconButton( //右侧添加第二个图标按钮
// icon: Icon(Icons.settings),
// onPressed: (){// print('settings');
// },
// )
// ],bottom: TabBar(tabs: <Widget>[ //配置Tabs菜单,系统会根据这里配置的是顺序对应下边body:TabBarView 里元素的顺序进行显示Tab(text: '热门',),Tab(text: '推荐',)],),),body: TabBarView(children: <Widget>[ListView(children: <Widget>[ListTile(title: Text('第一个tab'),),ListTile(title: Text('第一个tab'),),ListTile(title: Text('第一个tab'),)],),ListView(children: <Widget>[ListTile(title: Text('第二个tab'),),ListTile(title: Text('第二个tab'),),ListTile(title: Text('第二个tab'),)],)],),),);}
}
Home.dart
import 'package:flutter/material.dart';class HomePage extends StatefulWidget {@override_HomePageState createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {@overrideWidget build(BuildContext context) {return Center(child: Row(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[RaisedButton(child: Text('跳转到appBar'),onPressed: (){//路由跳转Navigator.pushNamed(context, '/appBarDemo');},)],),);}
}
Categroy.dart
import 'package:flutter/material.dart';class CategoryPage extends StatefulWidget {@override_CategoryPageState createState() => _CategoryPageState();
}class _CategoryPageState extends State<CategoryPage> {@overrideWidget build(BuildContext context) {return DefaultTabController(length: 4,child: Scaffold( //在Scaffold 里再嵌套ScaffoldappBar: AppBar(backgroundColor: Colors.black26,/*** 将顶部导航写在title里是为了防止,当Scaffold嵌套Scaffold时,发生两个顶部的bug,为了修复这个bug,* 我们就可以把顶部导航条写在title里*/title: Row(children: <Widget>[Expanded(child: TabBar(indicatorColor: Colors.blue, //设置指示器的颜色labelColor: Colors.blue, //设置:选中颜色unselectedLabelColor: Colors.white, //设置:未选中颜色indicatorSize: TabBarIndicatorSize.label, //选中时,底部指示条与文字一样长,默认是tabtabs: <Widget>[Tab(text: '热销'),Tab(text: '推荐',),Tab(text: '三',),Tab(text: '四',)],),)],),),body: TabBarView(children: <Widget>[ListView(children: <Widget>[ListTile(title: Text('第一个tab'),),ListTile(title: Text('第一个tab'),),ListTile(title: Text('第一个tab'),)],),ListView(children: <Widget>[ListTile(title: Text('第二个tab'),),ListTile(title: Text('第二个tab'),),ListTile(title: Text('第二个tab'),)],),ListView(children: <Widget>[ListTile(title: Text('第三个tab'),),ListTile(title: Text('第三个tab'),),ListTile(title: Text('第三个tab'),)],),ListView(children: <Widget>[ListTile(title: Text('第四个tab'),),ListTile(title: Text('第四个tab'),),ListTile(title: Text('第四个tab'),)],)],),),);}
}
Demo目录结构:
Futter基础11篇: 实现自定义AppBar 定义顶部Tab切换、底部Tab结合顶部Tab实现类似头条页面布局相关推荐
- 〖Python零基础入门篇㉛〗- 函数的定义与使用
订阅 Python全栈白宝书-零基础入门篇 可报销!白嫖入口-请点击我.推荐他人订阅,可获取扣除平台费用后的35%收益,文末名片加V! 说明:该文属于 Python全栈白宝书专栏,免费阶段订阅数量43 ...
- html5 tab菜单切换页面,11个常用的jQuery TAB切换菜单源码及制作教程
11个常用的jQuery TAB切换菜单源码及制作教程 Sponsor TAB切换式菜单可以方便为我们减少很多网页布局空间,而且用jQuery的话可以加入一些动画效果,比如渐变,向左右滑动等,提升一定 ...
- return error怎么定义_SpringBoot 系列 web 篇之自定义返回 Http Code 的 n 种姿势
200105-SpringBoot 系列 web 篇之自定义返回 Http Code 的 n 种姿势 虽然 http 的提供了一整套完整.定义明确的状态码,但实际的业务支持中,后端并不总会遵守这套规则 ...
- Xamarin XAML语言教程基础语法篇大学霸
Xamarin XAML语言教程基础语法篇大学霸 前 言 Xamarin是一个跨平台开发框架.它可以用来开发iOS.Android.Windows Phone和Mac的应用程序.使用Xamarin框 ...
- iOS 动画基础总结篇
iOS 动画基础总结篇 动画的大体分类(个人总结可能有误) 分类.png UIView 动画 属性动画 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 ...
- 鸟哥的linux私房菜-基础学习篇 读书笔记
从事linux工作一年多,算是能够熟练运用linux服务器,但仍觉得自己对Linux的原理,理论缺乏空洞,潜下心来认真阅读尘封的鸟哥经典,知识点很全,收获颇多,实践与知识结合,知行合一,对linux开 ...
- U3D_Shader编程(第二篇:基础夯实篇)
<U3D_Shader编程> ##<U3D_Shader编程>发布说明: ++++Shader一个高大上的领域,不管怎么样,我来了. ++++立钻哥哥从2018年开始正式对Sh ...
- Django基础(11): 表单集合Formset的高级用法详解
Formset(表单集)是多个表单的集合.Formset在Web开发中应用很普遍,它可以让用户在同一个页面上提交多张表单,一键添加多个数据,比如一个页面上添加多个用户信息.今天小编我就介绍下Djang ...
- 【Grasshopper基础12】打造自定义可复用的有按钮电池外观模版
作者:"咕咕咕?下一篇马上就写好了" 上一篇[基础11]向大家介绍了怎么在Grasshopper里制作自己的带有按钮的电池外观.从反馈来看,挺多读者对这个例子十分感兴趣,同时也私信 ...
- QT界面开发--基础学习篇一(上)
一.Qt简单介绍: 1.QT的简单理解: Qt简单的说就是一种可以跨平台的编程语言工具,可以直接类比C语言和C++. 且一般QT的代码逻辑也是以C语言和C++(也可以适用于像JS的语言),可以直观理解 ...
最新文章
- python3并发编程基础
- 转 容器生态系统 (续) - 每天5分钟玩转容器技术(3)
- Java中使用mysqldump实现mysql数据库备份并将sql文件打成zip压缩包
- phpstudy sqlsrv v8.1_phpStudy
- 会员中心 收藏动态消息创作SELECT LAST_INSERT_ID() 的使用和注意事项
- 李宏毅机器学习课程-Transfer Learning
- [GAN学习系列3]采用深度学习和 TensorFlow 实现图片修复(下)
- yarn 卸载包_0609-6.1.0-如何卸载CDH6.1
- React文档(十九)不使用ES6
- error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
- 192.168.8.1手机登陆_192.168.1.1手机登陆
- vs C++实现Socket通信、添加ws2_32.lib 动态链接库
- 龙华大浪注塑加工中模具原理及组成
- 国外免费图片素材站收集
- 建模阶段性总结(一)
- 企业邮箱注册—企业微信邮箱2.0时代正式来临
- 因果性与因果模型 | 中国人民大学哲学与认知科学明德讲坛
- 第十二章 软件壳(四)(代码抽取型壳)
- react native实现兼容Android与ios的视频播放器
- matlab 的 符号,MATLAB符号计算