一,概述

  TabBar,是材料设计(Material design)中很常用的一种横向标签页。在Android原生开发中,我们常用ViewPage或者一些常用的标签页开源库,来实现并行界面的横向滑动展示,在iOS原生开发中我们可以基于UICollectionView/UIButton来封装实现这一功能,在Flutter的世界中,TabBar是被定义在Material Component中,所以他的使用需要在MaterialApp中。通常,我们会在AppBar的底部部分结合TabBarView来使用TabBar。
    

二,Tab关键元素

  • TabController
    这是Tab页的控制器,用于定义Tab标签和内容页的坐标,还可配置标签页的切换动画效果等。
    TabController一般放入有状态控件中使用,以适应标签页数量和内容有动态变化的场景,如果标签页在APP中是静态固定的格局,则可以在无状态控件中加入简易版的DefaultTabController以提高运行效率,毕竟无状态控件要比有状态控件更省资源,运行效率更快。
  • TabBar
    Tab页的Title控件,切换Tab页的入口,一般放到AppBar控件下使用,内部有*Title属性。其子元素按水平横向排列布局,如果需要纵向排列,请使用ColumnListView控件包装一下。子元素为Tab类型的数组
  • TabBarView
    Tab页的内容容器,其内放置Tab页的主体内容。子元素可以是多个各种类型的控件。

三,构造函数  

  • TabController

    • DefalutTabController

       const DefaultTabController({
      Key key,
      @required this.length,
      this.initialIndex = ,
      @required this.child,
      }) : assert(initialIndex != null),
      assert(length >= ),
      assert(initialIndex >= && initialIndex < length),
      super(key: key);
    • TabController
      TabController({ int initialIndex = , @required this.length, @required TickerProvider vsync })
      : assert(length != null && length >= ),
      assert(initialIndex != null && initialIndex >= && (length == || initialIndex < length)),
      _index = initialIndex,
      _previousIndex = initialIndex,
      _animationController = AnimationController.unbounded(
      value: initialIndex.toDouble(),
      vsync: vsync,
      );
  • TabBar

    /**
    const TabBar({
    Key key,
    @required this.tabs,//显示的标签内容,一般使用Tab对象,也可以是其他的Widget
    this.controller,//TabController对象
    this.isScrollable = false,//是否可滚动
    this.indicatorColor,//指示器颜色
    this.indicatorWeight = 2.0,//指示器高度
    this.indicatorPadding = EdgeInsets.zero,//底部指示器的Padding
    this.indicator,//指示器decoration,例如边框等
    this.indicatorSize,//指示器大小计算方式,TabBarIndicatorSize.label跟文字等宽,TabBarIndicatorSize.tab跟每个tab等宽
    this.labelColor,//选中label颜色
    this.labelStyle,//选中label的Style
    this.labelPadding,//每个label的padding值
    this.unselectedLabelColor,//未选中label颜色
    this.unselectedLabelStyle,//未选中label的Style
    }) : assert(tabs != null),
    assert(isScrollable != null),
    assert(indicator != null || (indicatorWeight != null && indicatorWeight > 0.0)),
    assert(indicator != null || (indicatorPadding != null)),
    super(key: key);
    */
    • Tab

      const Tab({
      Key key,
      this.text,
      this.icon,
      this.child,
      }) : assert(text != null || child != null || icon != null),
      assert(!(text != null && null != child)), // TODO(goderbauer): https://github.com/dart-lang/sdk/issues/34180
      super(key: key);
  • TabBarView
      const TabBarView({
    Key key,
    @required this.children, //Tab页内容页组件数组集合
    this.controller, //TabController对象
    this.physics,
    this.dragStartBehavior = DragStartBehavior.start,
    }) : assert(children != null),
    assert(dragStartBehavior != null),
    super(key: key);

四,创建标签栏

  • 1.创建TabController

    • 使用默认的DefaultController

       /**2.创建Tabbar */
      @override
      Widget build(BuildContext context) {
      // TODO: implement build
      return new DefaultTabController(
      length: myTabs.length,
      child: new Scaffold(
      //AppBar
      appBar:new AppBar(
      title: new Text('顶部标签栏'),
      bottom: new TabBar(
      tabs: myTabs, //标签数组
      indicatorColor: Colors.blue,//指示器的颜色
      isScrollable: true,//是否滑动
      ),
      ) , /**3.绑定Tabbar 和 TabBarView */
      //body
      body: new TabBarView(
      children: myTabs.map((Tab tab){
      return new Center( child: new Text(tab.text));
      }).toList(),
      ),
      ),
      );
      }
    • 使用自定义的TabController的
      class TabBarDemoState extends State<TabBarDemo>
      with SingleTickerProviderStateMixin {
      TabController _tabController; //定义tabcontroller变量 @override
      void dispose() {
      _tabController.dispose(); //销毁
      super.dispose();
      } void initState() {
      super.initState();
      _tabController = new TabController(vsync: this, length: ); //创建
      } @override
      Widget build(BuildContext context) {
      return new Scaffold(
      appBar: new AppBar(
      title: new Text('顶部tab切换'),
      bottom: new TabBar(
      tabs: <Widget>[
      new Tab(
      icon: new Icon(Icons.directions_bike),
      ),
      new Tab(
      icon: new Icon(Icons.directions_boat),
      ),
      new Tab(
      icon: new Icon(Icons.directions_bus),
      ),
      ],
      controller: _tabController, //tabbar与自定义的tabcontroller绑定
      ),
      ),
      body: new TabBarView(
      controller: _tabController, //tabbarView与 自定义的tabController绑定
      children: <Widget>[
      new Center(child: new Text('自行车')),
      new Center(child: new Text('船')),
      new Center(child: new Text('巴士')),
      ],
      ),
      );
      }
  • 2.构建Tab数据/TabBarView数据
    /**1. 创建Tab数据 */
    final List<Tab> myTabs = <Tab>[
    new Tab(icon: new Icon(Icons.home),
    text:'首页',
    ),
    new Tab(
    icon: new Icon(Icons.message),
    text:'个人信息',
    ), new Tab(
    icon: new Icon(Icons.camera),
    text:'朋友圈',
    ),
    new Tab(
    icon: new Icon(Icons.access_alarm),
    text: '闹钟',
    )
    ];
  • 3. 创建Tabbar
    appBar:new AppBar(
    title: new Text('顶部标签栏'),
    bottom: new TabBar(
    tabs: myTabs, //标签数组
    indicatorColor: Colors.blue,//指示器的颜色
    isScrollable: true,//是否滑动
    ),
    )
  • 4.绑定TabBar 和 TabBarView
    /**3.绑定Tabbar 和 TabBarView */
    //body
    body: new TabBarView(
    children: myTabs.map((Tab tab){
    return new Center( child: new Text(tab.text));
    }).toList(),
    ),
  • 5.全部代码
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    // TODO: implement build
    return new MaterialApp(
    title: '顶部标签栏',
    theme: new ThemeData(
    primaryColor: Colors.red
    ),
    home: new App(),
    );
    }
    } class App extends StatelessWidget { /**1. 创建Tab数据 */
    final List<Tab> myTabs = <Tab>[
    new Tab(icon: new Icon(Icons.home),
    text:'首页',
    ),
    new Tab(
    icon: new Icon(Icons.message),
    text:'个人信息',
    ), new Tab(
    icon: new Icon(Icons.camera),
    text:'朋友圈',
    ),
    new Tab(
    icon: new Icon(Icons.access_alarm),
    text: '闹钟',
    )
    ]; /**2.创建Tabbar */
    @override
    Widget build(BuildContext context) {
    // TODO: implement build
    return new DefaultTabController(
    length: myTabs.length,
    child: new Scaffold(
    //AppBar
    appBar:new AppBar(
    title: new Text('顶部标签栏'),
    bottom: new TabBar(
    tabs: myTabs, //绑定标签数组
    indicatorColor: Colors.blue,//指示器的颜色
    isScrollable: true,//是否滑动
    ),
    ) , /**3.绑定Tabbar 和 TabBarView */
    //body
    body: new TabBarView(
    children: myTabs.map((Tab tab){
    return new Center( child: new Text(tab.text));
    }).toList(),
    ),
    ),
    );
    }
    }

五,总结

TabBarView和TabBar都有一个TabController的参数,TabbarView和TabBar就是由TabController来控制同步,点击某个Tab后,要同步显示对应的TabBarView,创建TabController有两种方式:

  • 第一种:使用系统自带的DefaultTabController,在Scaffold套一层DefaultTabController,这种方式TabBarView会自动查找这个tabController。

    @override
    Widget build(BuildContext context) {
    return new DefaultTabController();
    }
  • 第二种是自己定义一个TabController,实现SingleTickerProviderStateMixin
    参考上面“使用自定tabcontroller代码”

【Flutter学习】基本组件之TabBar顶部导航的更多相关文章

  1. Flutter学习笔记(17)--顶部导航TabBar、TabBarView、DefaultTabController

    如需转载,请注明出处:Flutter学习笔记(17)--顶部导航TabBar.TabBarView.DefaultTabController 上一篇我们说了BottmNavigationBar底部导航 ...

  2. 【Flutter学习】基本组件之AppBar顶部导航栏

    一,概述 AppBar 显示在app的顶部.AppBar包含5大部分,如下图: 二,构造函数及参数含义 构造函数 AppBar({ Key key, this.leading, //在标题前面显示的一 ...

  3. 【Flutter学习】组件学习之目录

    01. Flutter组件-Layout-Container-容器  02. Flutter组件-Text-Text-文本  03. Flutter组件-Text-RichText-富文本  04. ...

  4. 【Flutter学习】组件通信(父子、兄弟)

    一,概述 flutter一个重要的特性就是组件化.组件分为两种状态,一种是StatefulWidget有状态组件,一种是StatelessWidget无状态组件. 无状态组件不能更新状态,有状态组件具 ...

  5. Flutter学习笔记(16)--Scaffold脚手架、AppBar组件、BottomNavigationBar组件

    如需转载,请注明出处:Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解 今天的内容是Scaffold脚手架.AppBar组件.BottomNavigationBa ...

  6. uni-app 去除顶部导航栏

    自学uni-app第一天,因为有一点点的小程序和vue的基础所以感觉对uni-app有一点点的亲切感,从今天呢开始着手从登录页学习uni-app,记录一些用到的知识点,欢迎大家一起学习. 启动页隐藏顶 ...

  7. Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解

    如需转载,请注明出处:Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解 最近一段时间生病了,整天往医院跑,也没状态学东西了,现在是好了不少了,也该继续学习啦!!! ...

  8. Flutter学习笔记(18)--Drawer抽屉组件

    如需转载,请注明出处:Flutter学习笔记(18)--Drawer抽屉组件 Drawer(抽屉组件)可以实现类似抽屉拉出和推入的效果,可以从侧边栏拉出导航面板.通常Drawer是和ListView组 ...

  9. Flutter学习笔记(24)--SingleChildScrollView滚动组件

    如需转载,请注明出处:Flutter学习笔记(23)--多 在我们实际的项目开发中,经常会遇到页面UI内容过多,导致手机一屏展示不完的情况出现,以Android为例,在Android中遇到这类情况的做 ...

随机推荐

  1. 配置 Ceph 内外网分离

    https://www.jianshu.com/p/42ab1f6dc6de 1. 为什么要做内外网分离   先明确一下这么做的必要性.Ceph 的客户端,如 RADOSGW,RBD 等,会直接和 O ...

  2. 牛客多校训练营第九场 J - Symmetrical Painting (排序)

    J - Symmetrical Painting 题意 给你\(n\)个矩形, 左下角\((i-1,\ L_i)\), 右上角\((i,\ R_i)\), 找一条线\(l\)平行于\(x\)轴, 让这 ...

  3. Centos7.4 配置之MySQL 8.0【转】

    首先查看Mysql最新版本, 此时,目前最新版本为8.0. 开始安装前需要一些准备工作. 1,将本地的MariaDB或者已经安装的MySQL其他版本卸载. (一)卸载本地的本地的MariaDB: 由于 ...

  4. php7结合mongoDB插入数据

    php7结合mongoDB插入数据 代码如下: <?php $bulk = new MongoDB\Driver\BulkWrite;//1 $document = ['_id' => n ...

  5. AsyncTask2

    参考: AsyncTask - 简书http://www.jianshu.com/p/3b839d7a3fcf 前言 在android应用开发过程中,我们需要是时刻注意保证应用程序的稳定和UI操作响应 ...

  6. spring-cloud config配置中心

    这里那些概念不说,主要是记录下spring cloud config配置中心的服务端和客户端的一个demo. 服务端即提供统一配置文件 客户端即从服务端读取配置 1.新建一个spring boot项目 ...

  7. JS中获取元素使用getElementByID()、getElementsByName()、getElementsByTagName()的用法和区别

    Web标准下可以通过getElementById(), getElementsByName(), and getElementsByTagName()访问Documnent中的任一个标签:   1 g ...

  8. pip安装第三方库报错Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None))...

    pip安装第三方库时报错Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None))...,详细报错见下 ...

  9. 关系型数据库MySQL(三)_触发器

    简介 用来给保证数据完整性的一种方法,经常用于加强数据的完整性: 是与表事件相关的特殊的存储过程,与存储过程的唯一区别是触发器不能执行execute语句调用,而是在用户执行SQL语句时自动触发执行 执 ...

  10. jQuery获取地址url的参数

    例如:网址 http://localhost:26459/Master.aspx?5 $(function () { var url = location.search;   if (url.inde ...