前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter中的AppBar、TabBar和TabController——顶部切换栏是如何实现的

Flutter中的AppBar、TabBar和TabController——顶部切换栏是如何实现的

作者头像
拉维
发布2019-08-23 23:44:13
10.3K0
发布2019-08-23 23:44:13
举报
文章被收录于专栏:iOS小生活

顶部TabBar切换栏实现的第一种方式

在Flutter中,AppBar用于定义顶部的导航栏:

代码语言:javascript
复制
Scaffold(      appBar: AppBar(        title: Text("AppBarPageDemo"),      ),      body: Center(        child: Text("AppBarDemoPageContent"),      ),    );

效果如下:

实际上,AppBar 这个组件有许多的属性,我们通过这些属性,可以用来定义顶部导航栏的各种样式。下面我将为你一一说明这些属性的作用:

  • title,导航栏的标题,是一个Widget,通常显示为当前界面的标题文字,但是也可以放其他的组件,比如可以放TabBar。
  • backgroundColor,导航栏的背景颜色。
  • leading,在导航栏最左侧(标题前面)显示的组件,在首页通常显示应用的logo,在其他页面通常显示为返回按钮
  • actions,在导航栏右侧(标题后面)显示的组件组,通常使用IconButton来表示,可以放按钮组。
  • centerTitle,标题是否居中显示(无论是iOS还是Android)
  • isScrollable,顶部TabBar是否可以滚动。

以上几个属性是AppBar的常用属性,其使用代码如下:

代码语言:javascript
复制
Scaffold(      appBar: AppBar(        title: Text("AppBarPageDemo"), //标题        backgroundColor: Colors.pinkAccent, //背景颜色        //在导航栏标题左侧添加的一个组件        leading: IconButton(          onPressed: () => print("menu"),          icon: Icon(Icons.menu),        ),        //在导航栏标题右侧添加的组件组        actions: <Widget>[          IconButton(            onPressed: () => print("settings"),            icon: Icon(Icons.settings),          ),          IconButton(            onPressed: () => print("edit"),            icon: Icon(Icons.edit),          ),          IconButton(            onPressed: () => print("photo"),            icon: Icon(Icons.photo),          ),        ],        centerTitle: true,//标题是否居中展示      ),      body: Center(        child: Text("AppBarDemoPageContent"),      ),    );

上述代码的展示效果如下:

接下来我们来聊聊AppBar的bottom属性

一般而言,一个应用程序的首页底部是有一个TabBar的,用于切换各个功能页面,如下所示:

但是在有些情况下,我们需要在顶部也需要定义一个TabBar,用于切换不同的功能页面,如下面这种页面:

这个时候就需要用到AppBar的bottom属性了。也就是说,我们可以将AppBar的bottom属性值配置为一个TabBar组件,以实现在顶部添加TabBar的效果

但是,要想给AppBar的bottom配置TabBar,那么需要在Scaffold组件的外部再包一层DefaultTabController,代码如下:

代码语言:javascript
复制
DefaultTabController(      length: 2,//第1步,这里配置顶部tabbar的item个数      child: Scaffold(        appBar: AppBar(          //第2步,这里配置顶部tabbar          bottom: TabBar(            tabs: <Widget>[Tab(text: "热门"), Tab(text: "推荐")],          ),          title: Text("AppBarPageDemo"),           backgroundColor: Colors.pinkAccent,         ),        //第3步,这里配置顶部TabBar每一个item所对应的页面,其元素数量需要与TabBar的item数量保持一致        body: TabBarView(          children: <Widget>[            Text("热门页面"),            Text("推荐页面")          ],        ),      ),    );

运行结果如下:

对于上面代码,需要以下几点:

1,DefaultTabController的length属性用于配置顶部TabBar的item数量,需要与TabBar的tabs的元素数量,以及TabBarView的children的元素数量保持一致。

2,TabBar的tabs中的Tab元素,以及TabBarView的children中的页面元素是一一对应的,对应好了之后就可以在页面中对应展示了

3,在默认情况下,导航栏右上角有一个debug字样,如下:

如果我想把这个DEBUG字样去掉,那么可以在MaterialApp中配置debugShowCheckedModeBanner属性为false:

代码语言:javascript
复制
MaterialApp(        // home: Tabs(),        initialRoute: "/",//初始化的时候加载的路由        //统一处理命名路由        onGenerateRoute: prefix0.onGenerateRoute,        //去掉导航栏默认的debug图标        debugShowCheckedModeBanner: false,        );

再运行,我们发现DEBUG字样消失了:

我们上面讲的都是页面中只有一个AppBar的情况,这个时候如果想要加一个顶部TabBar,那么只需要配置APPBar的bottom属性即可。但是有些时候,我们会遇到不可自定义原始的AppBar的场景,而我们又想实现顶部TabBar的效果,此时我们就可以在页面中再加一个Scaffold组件,然后这样就有两个AppBar了。我们可以通过配置第二个AppBar来实现顶部TabBar的效果。

其实此时也是考验我们对AppBar以及TabBar的了解程度了。

AppBar是一个顶部导航栏,它的title属性用于配置标题,title对应的是一个组件,我们一般给title赋值为一个Text组件,但是也可根据需求给title赋值其他的组件。

AppBar的bottom属性,其对应的也是一个组件,我们一般给bottom属性赋值为TabBar组件,以实现顶部TabBar的效果

如果在一个页面中,一个Scaffold组件内部还嵌套了另外一个Scaffold组件,并且两个Scaffold组件都配置了appbar,那么就会是如下的展示效果:

以上是两个Scaffold的appBar都配置了title,但没有配置bottom。

好,我们现在来考虑一下,在有两个Scaffold的场景下,如何实现顶部TabBar的效果。我们可以像上面所讲的,给内层的Scaffold组件的appBar配置bottom属性值为TabBar组件,但是这样的话,内层的Scaffold组件的title的位置就会有一个留空,不好看,如下所示:

为了使页面更好看,我们可以将这个顶层的TabBar赋值给内层Scaffold的appBar的title属性,前面也说了,title对应的也是一个组件。这样就能完美解决留空的问题了。代码如下:

代码语言:javascript
复制
DefaultTabController(      length: 3,//顶部tabbar的元素数量      child: Scaffold(        appBar: AppBar(          //配置顶部tabbar          title: TabBar(            tabs: <Widget>[Tab(text: "热销"), Tab(text: "推荐"), Tab(text: "打折")],          ),        ),        //这里配置顶部Tabbar所对应的页面        body: TabBarView(          children: <Widget>[            Stack(              ...            ),            Text("222"),            Text("333")          ],        ),      ),    );

效果如下:

需要注意的一点是,如果我们想要通过配置AppBar的title或者bottom来实现顶部TabBar的效果,一定要在Scaffold组件外面再包一层DefaultTabController组件

好,现在我们已经知道该如何利用AppBar和TabBar来实现顶部Tabbar的视觉效果了。在本文的最后,我们来了解一下如何个性化设置顶部TabBar导航条。

TabBar的常用属性如下:

  • tabs,显示的标签内容,一般使用Tab对象,也可以是其他的Widget
  • isScrollable,是否可滚动
  • indicatorColor,底部指示条的颜色
  • indicatorWeight,底部指示条的高度
  • indicatorSize,指示器大小计算方式,TabBarIndicatorSize.label 跟文 字等宽,TabBarIndicatorSize.tab 跟每个 tab 等宽
  • labelColor,选中的文字颜色
  • unselectedLabelColor,未选中的文字颜色

示例代码如下:

代码语言:javascript
复制
DefaultTabController(      length: 6,//这里配置顶部tabbar的item个数      child: Scaffold(        appBar: AppBar(          //这里配置顶部tabbar          bottom: TabBar(            indicatorColor: Colors.yellow,            indicatorWeight: 10,            indicatorSize: TabBarIndicatorSize.label,            labelColor: Colors.orange,            unselectedLabelColor: Colors.white,            tabs: <Widget>[Tab(text: "热门"), Tab(text: "推荐"), Tab(text: "热门"), Tab(text: "推荐"), Tab(text: "热门"), Tab(text: "推荐")],          ),          title: Text("AppBarPageDemo"),           backgroundColor: Colors.pinkAccent,         ),        //这里配置顶部TabBar每一个item所对应的页面,其元素数量需要与TabBar的item数量保持一致        body: TabBarView(          children: <Widget>[            Text("热门页面"),            Text("推荐页面"),            Text("热门页面"),            Text("推荐页面"),            Text("热门页面"),            Text("推荐页面")          ],        ),      ),    );

展示效果如下:

顶部TabBar切换栏实现的第二种方式

上面我们已经实现了顶部TabBar切换栏的UI效果,但是上面这种方式我们不好监听页面切换,当页面中有网络请求、上拉刷新下拉加载等需求的时候,我们利用第一种方式就不容易实现。所幸我们还有第二种方式,那就是利用

TabController 来实现顶部Tab切换。

步骤如下:

1,页面(TabBarControllerPage)必须是继承自StatefulWidget,也就是说,页面必须是动态页面。

2,页面的state(_TabBarControllerPageState)要实现SingleTickerProviderStateMixin类。

3,在页面的state(_TabBarControllerPageState)中要声明并初始化一个TabController实例 (_tabController)

4,在 TabBar 和 TabBarView 中都配置一下 controller 属性

5,通过_tabController.addListener监听各种事件,以处理业务逻辑。

代码语言:javascript
复制
import 'package:flutter/material.dart';
//第1步,页面必须是动态页面class TabBarControllerPage extends StatefulWidget {  TabBarControllerPage({Key key}) : super(key: key);
  _TabBarControllerPageState createState() => _TabBarControllerPageState();}
//第2步,通过mixins“继承”自SingleTickerProviderStateMixin类class _TabBarControllerPageState extends State<TabBarControllerPage> with SingleTickerProviderStateMixin {    //第3步,声明TabController实例  TabController _tabController;
  @override  void initState() {    super.initState();    //第4步,初始化TabController实例    _tabController = TabController(      vsync: this,      length: 2,//这里指定TabBar中的item数量    );        //第5步,监听TabBar的各种页面切换    _tabController.addListener((){      print(_tabController.index);    });  }    @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text("TabBarControllerPage"),        bottom: TabBar(          //第6步,配置TabBar的controller          controller: _tabController,          tabs: <Widget>[Tab(text: "热门"), Tab(text: "推荐")],        ),      ),      body: TabBarView(        //第7步,配置TabBarView的controller        controller: _tabController,        children: <Widget>[Text("热门"), Text("推荐")],      ),    );  }}

效果如下:

第二种方式的好处是,我们可以在_tabController.addListener中监听一些Tab切换的事件,如下所示:

代码语言:javascript
复制
    _tabController.addListener((){      print(_tabController.index);    });

以上。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iOS小生活 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档