前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter】顶部导航栏实现 ( Scaffold | DefaultTabController | TabBar | Tab | TabBarView )

【Flutter】顶部导航栏实现 ( Scaffold | DefaultTabController | TabBar | Tab | TabBarView )

作者头像
韩曙亮
发布2023-03-29 09:14:14
2.5K0
发布2023-03-29 09:14:14
举报

文章目录

一、Scaffold 组件


Flutter 中的 Scaffold 组件实现了基础的材料设计 ( Material Design ) 可视化布局结构 ;

Scaffold 提供了显示左侧侧拉导航栏 , 底部导航 , 浮动按钮等 API ;

Scaffold 构造函数如下 :

代码语言:javascript
复制
class Scaffold extends StatefulWidget {
  /// Creates a visual scaffold for material design widgets.
  const Scaffold({
    Key? key,
    this.appBar,	// 顶部的标题栏
    this.body,		// 中间显示的核心部分 , 标题栏下面的部分都是  
    this.floatingActionButton,			// 右下角的悬浮按钮 ( 可改变位置 )
    this.floatingActionButtonLocation,
    this.floatingActionButtonAnimator,
    this.persistentFooterButtons,
    this.drawer,	// 侧拉导航栏 
    this.onDrawerChanged,
    this.endDrawer,
    this.onEndDrawerChanged,
    this.bottomNavigationBar,
    this.bottomSheet,
    this.backgroundColor,
    this.resizeToAvoidBottomInset,
    this.primary = true,
    this.drawerDragStartBehavior = DragStartBehavior.start,
    this.extendBody = false,
    this.extendBodyBehindAppBar = false,
    this.drawerScrimColor,
    this.drawerEdgeDragWidth,
    this.drawerEnableOpenDragGesture = true,
    this.endDrawerEnableOpenDragGesture = true,
    this.restorationId,
  }) : assert(primary != null),
       assert(extendBody != null),
       assert(extendBodyBehindAppBar != null),
       assert(drawerDragStartBehavior != null),
       super(key: key);

二、实现顶部导航栏


实现顶部导航栏需要三个组件 :

  • TabBar : 该组件就是导航栏组件 , 设置多个图标按钮 ;
  • TabBarView : 该组件是被导航的组件 , 设置多个布局结构 , 同时只能显示一个 ;
  • DefaultTabController : 该组件用于关联控制 TabBar 和 TabBarView 组件 ;

界面组件中 , 根组件肯定是 MaterialApp , 然后下一层组件就是 DefaultTabController , 使用 DefaultTabController 包裹 Scaffold , 然后在 Scaffold 中定义的 TabBar 和 TabBarView 就会被关联再一起 ;

注意三个相等的值 :

DefaultTabController length 长度

等于

TabBar 子组件个数

等于

TabBarView 子组件个数

Google 官方给出的文档 :

[TabBar], which displays a row of tabs. ( 显示一行标签 ) [TabBarView], which displays a widget for the currently selected tab. ( 显示当前选中的标签对应的组件 ) [TabController], which coordinates tab selection between a [TabBar] and a [TabBarView]. ( 用于关联标签与选项卡 ) https://material.io/design/components/tabs.html

三、DefaultTabController 导航标签控制组件


DefaultTabController 用于关联 TabBar 和 TabBarView 组件 ;

由于 TabBar 中的组件都是无状态组件 , 或者不同的父类组件 , 导致创建 TabController 不方便时 , 就会使用该 DefaultTabController 组件 ;

DefaultTabController 组件的 length 参数必须不为空 , 并且大于 1 , length 的个数必须等于 TabBar 和 TabBarView 的个数 ;

initialIndex 初始索引值参数必须不能为空

DefaultTabController 构造函数原型 :

代码语言:javascript
复制
  /// 为给定的子组件创建一个默认的导航控制器
  ///
  /// length 参数必须不为空 , 并且大于 1 ;
  /// length 的个数必须等于 TabBar 和 TabBarView 的个数 ;
  /// 
  /// initialIndex 初始索引值参数必须不能为空 
  const DefaultTabController({
    Key? key,
    required this.length,
    this.initialIndex = 0,
    required this.child,
  }) : assert(initialIndex != null),
       assert(length >= 0),
       assert(length == 0 || (initialIndex >= 0 && initialIndex < length)),
       super(key: key);

Google 官方给出的代码示例 :

代码语言:javascript
复制
class MyDemo extends StatelessWidget {
  final List<Tab> myTabs = <Tab>[
    Tab(text: 'LEFT'),
    Tab(text: 'RIGHT'),
  ];
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: myTabs.length,
      child: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            tabs: myTabs,
          ),
        ),
        body: TabBarView(
          children: myTabs.map((Tab tab) {
            final String label = tab.text.toLowerCase();
            return Center(
              child: Text(
                'This is the $label tab',
                style: const TextStyle(fontSize: 36),
              ),
            );
          }).toList(),
        ),
      ),
    );
  }
}

四、TabBar 导航按钮组件


TabBar 组件主要用于封装导航栏的图标按钮 , 主要设置一组 Tab 组件 ;

通常放在 AppBar 组件的底部 , 也就是赋值给 AppBar.bottom , 与 TabBarView 结合起来使用 ;

TabBar 中 Tab 子组件的个数 , TabController 中的 length 长度 , TabBarView 中子组件的个数 , 三者必须相等 ;

TabBar 构造函数 :

代码语言:javascript
复制
  const TabBar({
    Key? key,
    required this.tabs,
    this.controller,
    this.isScrollable = false,
    this.indicatorColor,
    this.automaticIndicatorColorAdjustment = true,
    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.overlayColor,
    this.mouseCursor,
    this.enableFeedback,
    this.onTap,
    this.physics,
  }) : 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);

官方提供的 TabBar 代码示例 :

代码语言:javascript
复制
late TabController _tabController;
 @override
 void initState() {
   super.initState();
   _tabController = TabController(length: 3, vsync: this);
 }
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text('TabBar Widget'),
       bottom: TabBar(
         controller: _tabController,
         tabs: <Widget>[
           Tab(
             icon: Icon(Icons.cloud_outlined),
           ),
           Tab(
            icon: Icon(Icons.beach_access_sharp),
           ),
           Tab(
             icon: Icon(Icons.brightness_5_sharp),
           ),
         ],
       ),
     ),
     body: TabBarView(
       controller: _tabController,
       children: <Widget>[
         Center(
           child: Text('It\'s cloudy here'),
         ),
         Center(
           child: Text('It\'s rainy here'),
         ),
         Center(
            child: Text('It\'s sunny here'),
         ),
       ],
     ),
   );
 }

五、Tab 标签组件


Tab 组件是 TabBar 组件的子组件 , 每个 TabBar 组件需要设置若干个 Tab 组件 ( 至少一个 ) ;

Tab 构造函数 :

代码语言:javascript
复制
  /// 创建一个材料设计风格的选项卡.
  ///
  /// 至少设置一个 text 文本和 icon 图标 child 必须为非空 .
  const Tab({
    Key? key,
    this.text,
    this.icon,
    this.iconMargin = const EdgeInsets.only(bottom: 10.0),
    this.child,
  }) : assert(text != null || child != null || icon != null),
       assert(text == null || child == null),
       super(key: key);

代码示例 :

代码语言:javascript
复制
bottom: TabBar(
  /// 可左右滑动
  isScrollable: true,
  /// 设置顶部导航栏的图标
  tabs: datas.map((TabData data) {
    /// 导航栏的图标及文本
    return Tab(
      text: data.title,
      icon: Icon(data.icon),
    );
  }).toList(),
),

六、TabBarView 导航主体内容组件


显示 TabBar 中当前选中的 Tab 标签对应的组件 ;

TabBarView 初始化时 , 可以只为其设置 children 参数 , 类型是 List<Widget> ;

TabBarView 构造函数 :

代码语言:javascript
复制
  const TabBarView({
    Key? key,
    required this.children,
    this.controller,
    this.physics,
    this.dragStartBehavior = DragStartBehavior.start,
  }) : assert(children != null),
       assert(dragStartBehavior != null),
       super(key: key);

七、完整代码示例


代码语言:javascript
复制
import 'package:flutter/material.dart';

void main() {
  runApp(
      TabBarWidget()
  );
}

/// 导航栏数据集合
const List<TabData> datas = const <TabData>[
  const TabData(title: '3D', icon: Icons.threed_rotation),
  const TabData(title: '打印机', icon: Icons.print),
  const TabData(title: '动画', icon: Icons.animation),
  const TabData(title: '变换', icon: Icons.transform),
  const TabData(title: '高度', icon: Icons.height),
  const TabData(title: '描述', icon: Icons.description),
  const TabData(title: '向前', icon: Icons.forward),
  const TabData(title: '相机', icon: Icons.camera),
  const TabData(title: '设置', icon: Icons.settings),
  const TabData(title: '学位', icon: Icons.school),
];

/// 顶部导航栏核心页面
class TabBarWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    /// 材料设计应用组件 , 一般作为页面的根组件
    return MaterialApp(

      /// 用于将 TabBar 和 TabBarView 封装起来
      home: DefaultTabController(
        length: datas.length,

        /// 主界面框架
        child: Scaffold(

          /// 标题栏
          appBar: AppBar(

            /// 标题栏标题
            title: const Text('顶部导航栏'),

            /// 设置顶部导航栏
            bottom: TabBar(
              /// 可左右滑动
              isScrollable: true,

              /// 设置顶部导航栏的图标
              tabs: datas.map((TabData data) {

                /// 导航栏的图标及文本
                return Tab(
                  text: data.title,
                  icon: Icon(data.icon),
                );

              }).toList(),
            ),
          ),

          /// 导航栏控制的左右轮播的组件
          body: TabBarView(

            /// 界面显示的主体 , 通过 TabBar 切换不同的本组件显示
            children: datas.map((TabData choice) {
              return Padding(
                padding: const EdgeInsets.all(10.0),
                child: TabContent(data: choice),
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

/// 通过 TabBar 导航栏切换展示的主要内容
/// 用于在 TabBarView 中显示的组件
class TabContent extends StatelessWidget {
  const TabContent({Key key, this.data}) : super(key: key);

  /// 根据该数据条目生成组件
  final TabData data;

  @override
  Widget build(BuildContext context) {
    TextStyle textStyle = TextStyle(color: Colors.yellow, fontSize: 50);
    return Card(

      /// 设置 20 像素边距
      margin: EdgeInsets.all(20),

      /// 设置阴影
      elevation: 10,

      /// 卡片颜色黑色
      color: Colors.black,

      /// 卡片中的元素居中显示
      child: Center(

        /// 垂直方向的线性布局
        child: Column(

          /// 在主轴 ( 垂直方向 ) 占据的大小
          mainAxisSize: MainAxisSize.min,

          /// 居中显示
          crossAxisAlignment: CrossAxisAlignment.center,

          children: <Widget>[

            /// 设置图标
            Icon(data.icon, size: 128.0, color: Colors.green),

            /// 设置文字
            Text(data.title, style: TextStyle(color: Colors.yellow, fontSize: 50)),

          ],
        ),
      ),
    );
  }
}

/// 封装导航栏的图标与文本数据
class TabData {
  /// 导航数据构造函数
  const TabData({this.title, this.icon});

  /// 导航标题
  final String title;

  // 导航图标
  final IconData icon;
}

运行效果 :

在这里插入图片描述
在这里插入图片描述

八、相关资源


参考资料 :

重要的专题 :

博客源码下载 :

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、Scaffold 组件
  • 二、实现顶部导航栏
  • 三、DefaultTabController 导航标签控制组件
  • 四、TabBar 导航按钮组件
  • 五、Tab 标签组件
  • 六、TabBarView 导航主体内容组件
  • 七、完整代码示例
  • 八、相关资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档