秒懂Flutter Widgets之Tabs构建 (TabBar,TabBarView, TabController)

[版权申明]非商业目的注明出处可自由转载
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/113094263
出自:shusheng007

概述

Flutter 秒懂系列大部分会着眼于应用层面,不会过于深入原理,否则会以深入理解为题。

那为啥不写深入理解呢?

  1. 本人目前阶段也是刚接触Flutter,自认为也是个二把刀,怕误人子弟。
  2. 对于大部分人,熟练掌握应用层就足够了。

让我们言归正传,Flutter将一切都抽象成了Widget,而我们日常工作大部分时间其实是在使用各种UI Widget构建常见UI页面,非UI widget反而不多。所以我就先总结UI相关的Widget常用方法。

那为什么先写TabBar呢?是因为它简单吗?不是,是因为我最近刚好用到啦,呵呵。。

目标UI

今天介绍的控件用来构建如下类型的UI,这也是一种常见的UI。

在这里插入图片描述

控件

涉及到两个Widget外加一个控制器:

  • TabBar

负责构建那些tab

  • TabBarView

负责构建每个tab的内容页

  • TabController (类)一般使用 DefaultTabController 即可

将TabBar与TabBarView联动起来,例如点击tab,则切换相应的view。切换view则选择相应的tab。

使用方法

  1. 构建一个TabBar
  final tabs = <Tab>[
    Tab(
      text: '第一页',
    ),
    Tab(
      icon: Icon(Icons.add_alert_rounded),
    ),
    Tab(
      icon: Icon(Icons.accessibility_rounded),
    )
  ];
  
  TabBar(tabs: tabs, ),

TabBar有很多属性,但是只有tabs是必须的,这个也很好理解。

 const TabBar({
    Key key,
    @required this.tabs,
    this.controller,
    ...
    })

如上源码所示, tabs 一个List<Widget>类型, 但是我们一个使用List<Tab>就可以了满足大部分需求了。值得注意的是里面还有一个可选的TabController类型的属性

  1. 构建相应的TabBarView
TabBarView(children: [
              Icon(Icons.supervised_user_circle_rounded),
              Icon(Icons.add_alert_rounded),
              Icon(Icons.accessibility_rounded),
            ]),

也非常简单,传入与tabs对应数量的View就可以了。

 const TabBarView({
    Key key,
    @required this.children,
    this.controller,
    ...
  })

如上所以,其也只有一个必选参数:children,类型为List<Widget>。关键看里面也有一个可选的TabController类型的属性,也许你已经猜到了,TabBar 与 TabBarView 这两个控件就是通过将这个属性设置为同一个TabController来实现联动的。

  1. 使用TabController 将TabBar 与 TabBarView联系起来

此处为简单我们使用DefaultTabController

下面是其源码,非常简单。传入tabs的数量,以及View即可

  const DefaultTabController({
    Key key,
    @required this.length,
    this.initialIndex = 0,
    @required this.child,
  }

此处值得注意的是我们使用了ScaffoldAppBar,我们的TabBar是传递给AppBarbottom属性的。也就是说tab是位于顶部AppBar的下面的。如果不想要在下面,可以将TabBar赋值给AppBartitle属性,或者直接代替AppBar也是可以的,剩下的就是你自己大胆尝试了,但是据我的尝试Scaffold是必须要的,不然会黑屏。

要想使tab位于底部,可以将TabBar赋值给ScaffoldbottomNavigationBar 属性即可

完整代码如下

class TabBarView extends StatelessWidget {
  final tabs = <Tab>[
    Tab(
      text: '第一页',
    ),
    Tab(
      icon: Icon(Icons.add_alert_rounded),
    ),
    Tab(
      icon: Icon(Icons.accessibility_rounded),
    )
  ];

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: tabs.length,
      child: Scaffold(
        appBar: AppBar(
          title: Text('TabBar'),
          bottom: TabBar(
            tabs: tabs,
          ),
        ),
        body: TabBarView(children: [
          Icon(Icons.supervised_user_circle_rounded),
          Icon(Icons.add_alert_rounded),
          Icon(Icons.accessibility_rounded),
        ]),
      ),
    );
  }
}

经过以上3步即可完成Tab UI的的构建,其中TabBar中有很多可以配置Tab样式的属性,建议自己摸索一下,不然看了也记不住。当时发现默认样式达不到你的要求时,先去看看有没有一个属性可以配置,大部分情况下是没问题的。

进阶

下面我们提供一些稍微进阶的用法。

如何使用自定义TabController

非常简单,创建一个TabController 对象,同时赋值给TabBarTabBarView即可。

class EnhanceTabBar extends StatefulWidget {
  @override
  _EnhanceTabBarState createState() => _EnhanceTabBarState();
}

class _EnhanceTabBarState extends State<EnhanceTabBar>
    with SingleTickerProviderStateMixin {
  TabController _tabController;
   final  tabs = <Tab>[
      Tab(
        icon: Icon(Icons.add_alert_rounded),
      ),
      Tab(
        icon: Icon(Icons.accessibility_rounded),
      )
    ];
  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: tabs.length, vsync: this);
    _tabController.addListener(() {
      if (!_tabController.indexIsChanging) {
        //监听tab变化
        log('${_tabController.index}');        
      }
    });
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          tabs: tabs,
          controller: _tabController,
        ),
      ),
      body: TabBarView(controller: _tabController, children: [
        Icon(Icons.add_alert_rounded),
        Icon(Icons.accessibility_rounded),
      ]),
    );
  }
}

如何给DefaultTabController设置Tab切换监听

使用 DefaultTabController.of(context) 获得TabController,然后加上监听即可。注意那个Builder,因为要保证BuildContext有层级关系才能获取到。

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: tabs.length,
      child:  Builder(
        builder: (BuildContext context) {
          final TabController tabController = DefaultTabController.of(context);
          tabController.addListener(() {
            if (!tabController.indexIsChanging) {
               //监听tab切换
            }
          });

          return Scaffold(
            appBar: AppBar(
              bottom: TabBar(
                tabs: tabs,
              ),
            ),
            body: TabBarView(children: [
				...
            ]),
          );
        },
      ),
    );
  }

如何自定义Tab指示器

Tab指示器就是默认样式中切换tab时候下面那个白条条,通过设置TabBarindicator即可,它需要一个Decoration 类型的参数。默认使用的是UnderlineTabIndicator

TabBar(
        tabs: tabs,
        indicator: UnderlineTabIndicator(),
      ),

Flutter 提供了很多自定义这个指示器的实现类BoxDecorationShapDecorationUnderlineTabIndicator 还有一个玩一样的东东FlutterLogoDecoration

在这里插入图片描述

总结

以上就是关于如何构建Tabs类型UI的一些知识,希望你们get到啦。点赞收藏不抓瞎,关注博主不迷路…

源码下载:flutter_app_learn

最后为自己拉个票吧,我支不量力的参加了2020年的博客之星评选,我知道现在拉票有点晚,但是还是希望小伙伴们能随手支持一下。
方法:点击下面的链接进入投票页面,为ShuSheng007贡献上您珍贵的一票,谢谢。
2020年博客之星

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要从另一个页面跳转到TabBarTabBarView中的页面,您可以使用Flutter的导航机制。以下是一个简单的示例: 假设您有两个页面:HomePage和TabbedPage。HomePage包含一个按钮,点击该按钮将导航到TabbedPage,TabbedPage包含TabBarTabBarView,每个标签对应一个页面。 在HomePage中,您可以使用Navigator.push方法跳转到TabbedPage: ```dart import 'package:flutter/material.dart'; import 'tabbed_page.dart'; class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: RaisedButton( child: Text('Go to Tabbed Page'), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => TabbedPage()), ); }, ), ), ); } } void main() { runApp(MaterialApp( home: HomePage(), )); } ``` 在TabbedPage中,您可以创建一个DefaultTabController来管理TabBarTabBarView,并在TabBar中定义标签。每个标签对应一个页面。 ```dart import 'package:flutter/material.dart'; import 'tab_page.dart'; class TabbedPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Tabbed Page'), bottom: TabBar( tabs: [ Tab(text: 'Page 1'), Tab(text: 'Page 2'), ], ), ), body: TabBarView( children: [ TabPage(title: 'Page 1'), TabPage(title: 'Page 2'), ], ), ); } } class TabPage extends StatelessWidget { final String title; TabPage({this.title}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text(title), ), ); } } ``` 在上面的示例中,TabbedPage使用TabBarTabBarView来展示两个页面。每个页面由TabPage小部件表示。您可以根据实际需求自定义这些页面。 当您从HomePage点击按钮跳转到TabbedPage时,将会显示TabBarTabBarView,并且您可以在TabBar中进行不同标签页之间的切换。 希望对您有所帮助!如果有任何其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShuSheng007

亲爱的猿猿,难道你又要白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值