Flutter开发七、实现App底部tab切换和AppBar中自定义顶部导航
需要用到的知识点StatefulWidgetbottomNavigationBar等组件
·
目录
App底部tab切换
除了主界面以外,新建两个界面,界面布局如下
界面:home.dart
import 'package:flutter/material.dart'; class HomePage extends StatefulWidget { HomePage({Key key}) : super(key: key); _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { // TODO: implement build return Container( width: 300, height: 300, color: Colors.green, ); } }界面:user.dart
import 'package:flutter/material.dart'; class UserPage extends StatefulWidget { UserPage({Key key}) : super(key: key); _UserPageState createState() => _UserPageState(); } class _UserPageState extends State<UserPage> { @override Widget build(BuildContext context) { // TODO: implement build return Container( width: 300, height: 300, color: Colors.red, ); } }底部导航栏:tabs.dart
bottomNavigationBar组件,可以直接显示底部按钮,onTap方法进行交互,
setState方法可以实时渲染修改界面,currentIndex表示当前按下的位置
import 'package:flutter/material.dart'; import 'package:project/views/home.dart'; import 'package:project/views/user.dart'; class Tabs extends StatefulWidget{ Tabs({Key key}):super(key:key); _TabsState createState()=>_TabsState(); } class _TabsState extends State<Tabs>{ int _currentIndex=0; //下面的三个方法都是三个界面的方法 List _pageList=[ UserPage(), HomePage(), ]; @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( appBar: AppBar( title: Text('底部导航栏切换'), ), /** * 切换底部导航栏的时候动态修改body内容 */ body:this._pageList[this._currentIndex], bottomNavigationBar: BottomNavigationBar( currentIndex: this._currentIndex, //实现底部导航栏点击选中功能 onTap: (int index){ // this._currentIndex=index;//不会重新渲染 setState(() { this._currentIndex=index; }); }, items: [ BottomNavigationBarItem( icon: Icon(Icons.home), title: Text("首页") ), BottomNavigationBarItem( icon: Icon(Icons.supervised_user_circle), title: Text("用户") ), // BottomNavigationBarItem( // icon: Icon(Icons.category), // title: Text("分类") // ), // BottomNavigationBarItem( // icon: Icon(Icons.settings), // title: Text("我的") // ) ], ), ); } }主界面
import 'package:flutter/material.dart'; import 'widgets/components/Tab/tabs.dart'; void main() { // main函数是app程序的入口 // runApp接受的widget将成为widget树的根(ps:相当于顶层容器) runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( home:Tabs() ); } }效果
其他
底部导航栏超过三个不显示
底部导航栏的类型会改变其项的显示方式。如果未指定,则自动设置为
BottomNavigationBarType。当少于4个项目时修正,
BottomNavigationBarType。否则转移。
BottomNavigationBarType。修正了少于四个项目时的默认设置。选中的项目是用fixedColor呈现的非空,否则为主题的主题数据。primaryColor使用。的导航栏的背景色是默认的材质背景色颜色,ThemeData。帆布色(基本上是不透明的白色)。
BottomNavigationBarType。移动,当有四个或更多项时的默认值。所有的项目都是白色的,导航栏是白色的底色是一样的BottomNavigationBarItem。选定项目的背景色。在这个假设每个项目都有不同的背景颜色和背景色将与白色形成很好的对比。
处理方式:bottomNavigationBar 添加:
type: BottomNavigationBarType.fixed,顶部导航
常见属性:
AppBar({ Key key, this.leading, //在标题前面显示的一个控件,在首页通常显示应用的 logo;在其他界面通常显示为返回按钮 this.automaticallyImplyLeading = true, this.title, //Toolbar 中主要内容,通常显示为当前界面的标题文字 this.actions, //一个 Widget 列表,代表 Toolbar 中所显示的菜单,对于常用的菜单,通常使用 IconButton 来表示;对于不常用的菜单通常使用 PopupMenuButton 来显示为三个点,点击后弹出二级菜单 this.flexibleSpace,//一个显示在 AppBar 下方的控件,高度和 AppBar 高度一样,可以实现一些特殊的效果,该属性通常在 SliverAppBar 中使用 this.bottom, //一个 AppBarBottomWidget 对象,通常是 TabBar。用来在 Toolbar 标题下面显示一个 Tab 导航栏 this.elevation = 4.0,//纸墨设计中控件的 z 坐标顺序,默认值为 4,对于可滚动的 SliverAppBar,当 SliverAppBar 和内容同级的时候,该值为 0, 当内容滚动 SliverAppBar 变为 Toolbar 的时候,修改 elevation 的值 this.backgroundColor,//APP bar 的颜色,默认值为 ThemeData.primaryColor。改值通常和下面的三个属性一起使用 this.brightness,//App bar 的亮度,有白色和黑色两种主题,默认值为 ThemeData.primaryColorBrightness this.iconTheme, //App bar 上图标的颜色、透明度、和尺寸信息。默认值为 ThemeData.primaryIconTheme this.textTheme, //App bar 上的文字样式。默认值为 ThemeData.primaryTextTheme this.primary = true, this.centerTitle,//标题是否居中显示,默认值根据不同的操作系统,显示方式不一样,true居中 false居左 this.titleSpacing = NavigationToolbar.kMiddleSpacing, this.toolbarOpacity = 1.0, this.bottomOpacity = 1.0, })自定义AppBar
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: Text("This is AppBar"), backgroundColor: Colors.lightBlue, centerTitle: true, leading: IconButton( onPressed: () { Navigator.pushNamed(context, "/"); }, icon: Icon(Icons.menu), ), actions: <Widget>[ IconButton( onPressed: () { print('settings'); }, icon: Icon(Icons.settings), ), IconButton( onPressed: () { print('search'); }, icon: Icon(Icons.search), ), ], ), body: Center( child: Text("AppBar"), ), ), ); } }
顶部Tab切换
- tabs :显示的标签内容,一般使用 Tab 对象,也可以是其他的 Widget
- controller :TabController 对象
- isScrollable :是否可滚动
- indicatorColor :指示器颜色
- indicatorWeight :指示器高度
- indicatorPadding :底部指示器的 Padding
- indicator :指示器 decoration,例如边框等
- indicatorSize :指示器大小计算方式,TabBarIndicatorSize.label 跟文字等宽,TabBarIndicatorSize.tab 跟每个 tab 等宽
- labelColor :选中 label 颜色
- labelStyle :选中 label 的 Style
- labelPadding :每个 label 的 padding 值
- unselectedLabelColor :未选中 label 颜色
- unselectedLabelStyle :未选中 label 的 Style
- leading → Widget - 在标题前面显示的一个控件,在首页通常显示应用的 logo;在其他界面通常显示为返回按钮。
- title → Widget - Toolbar 中主要内容,通常显示为当前界面的标题文字。
- actions → List - 一个 Widget 列表,代表 Toolbar 中所显示的菜单,对于常用的菜单,通常使用 IconButton 来表示;对于不常用的菜单通常使用 PopupMenuButton 来显示为三个点,点击后弹出二级菜单。
- bottom → PreferredSizeWidget - 一个 AppBarBottomWidget 对象,通常是 TabBar。用来在 Toolbar 标题下面显示一个 Tab 导航栏。
- elevation → double - 控件的 z 坐标顺序,默认值为 4,对于可滚动的 SliverAppBar,当 SliverAppBar 和内容同级的时候,该值为 0, 当内容滚动 SliverAppBar 变为 Toolbar 的时候,修改 elevation 的值。
- flexibleSpace → Widget - 一个显示在 AppBar 下方的控件,高度和 AppBar 高度一样,可以实现一些特殊的效果,该属性通常在 SliverAppBar 中使用。
- backgroundColor → Color - Appbar 的颜色,默认值为 ThemeData.primaryColor。改值通常和下面的三个属性一起使用。
- brightness → Brightness - Appbar 的亮度,有白色和黑色两种主题,默认值为 ThemeData.primaryColorBrightness。
- iconTheme → IconThemeData - Appbar 上图标的颜色、透明度、和尺寸信息。默认值为 ThemeData.primaryIconTheme。
- textTheme → TextTheme - Appbar 上的文字样式。
- centerTitle → bool - 标题是否居中显示,默认值根据不同的操作系统,显示方式不一样。
toolbarOpacity → double
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: "title")); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return DefaultTabController( length: 3, child: Scaffold( appBar: AppBar( title: Text("This is AppBar"), backgroundColor: Colors.lightBlue, centerTitle: true, actions: <Widget>[ IconButton( onPressed: () { print('search'); }, icon: Icon(Icons.search), ), ], bottom: TabBar( isScrollable: true, // 是否可滚动 labelStyle:TextStyle(fontSize: 20), // 选中 label 的 Style unselectedLabelStyle:TextStyle(fontSize: 15), // 未选中 label 的 Style indicatorColor:Colors.lightBlueAccent, // 指示器颜色 unselectedLabelColor: Colors.white, // 未选中 label 颜色 labelColor:Colors.lightBlueAccent, // 选中 label 颜色 tabs: <Widget>[ // 显示的标签内容 Tab( text: "关注", ), Tab( text: "推荐", ), Tab( text: "视频", ), ], ), ), body: TabBarView( children: <Widget>[ ListView( children: <Widget>[ ListTile( title: Text("Text"), ) ], ), ListView( children: <Widget>[ ListTile( title: Text("Text"), ) ], ), ListView( children: <Widget>[ ListTile( title: Text("Text"), ) ], ), ], ) ), ); } }
底部TabBar集成顶部TabBar
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: "title")); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { /** * 在已集成的Scaffold中的TabBar要集成顶部TabBar */ return DefaultTabController( length: 2, child: Scaffold( appBar: AppBar( title: Row( children: <Widget>[ Expanded( child: TabBar( tabs: <Widget>[ Tab(text: "个人通讯录",), Tab(text: "公司通讯录",), ], ), ) ], ), ), body: TabBarView( children: <Widget>[ Center(child: Text("个人通讯录"),), Center(child: Text("公司通讯录"),), ], ), ), ); } }
设置appBar的高度
Scaffold ( appBar: PreferredSize( child: AppBar(), preferredSize: Size.fromHeight(screenSize.height * 0.07) ) );TabController动态加载顶部导航和内容
按照网上在initState里初始化TabController一直报错,就换了种思路
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: "title")); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin { TabController _tabController({length, vsync}) { TabController tabController = TabController(length:length, vsync: vsync); tabController.addListener(() { print(tabController.index); }); return tabController; } @override void initState() { super.initState(); // _tabController = new TabController(length:2, vsync: this); //可以加监听事件 // _tabController!.addListener((){ // print(_tabController!.index); // }); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { TabController t = _tabController(length:2, vsync: this); return Scaffold( appBar: AppBar( title: Text("TabBarController"), bottom: TabBar( tabs: <Widget>[ Tab(text: "关注",), Tab(text: "热门",), ], controller: t, ), ), body: TabBarView( children: [ Center(child: Text("关注"),), Center(child: Text("热门"),), ], controller: t, ), ); } }![]()
更多推荐










所有评论(0)