当前位置:   article > 正文

37、Flutter之TabBarView组件_flutter tabview

flutter tabview

TabBarView 是 Material 组件库中提供了 Tab 布局组件,通常和 TabBar 配合使用。

TabBarView


TabBarView 封装了 PageView,它的构造方法很简单

  1. TabBarView({
  2. Key? key,
  3. required this.children, // tab 页
  4. this.controller, // TabController
  5. this.physics,
  6. this.dragStartBehavior = DragStartBehavior.start,
  7. })

TabController 用于监听和控制 TabBarView 的页面切换,通常和 TabBar 联动。如果没有指定,则会在组件树中向上查找并使用最近的一个 DefaultTabController

TabBar


TabBar 为 TabBarView 的导航标题,如下图所示:

 TabBar 有很多配置参数,通过这些参数我们可以定义 TabBar 的样式,很多属性都是在配置 indicator 和 label,拿上图来举例,Label 是每个Tab 的文本,indicator 指 “历史” 下面的白色下划线。

  1. const TabBar({
  2. Key? key,
  3. required this.tabs, // 具体的 Tabs,需要我们创建
  4. this.controller,
  5. this.isScrollable = false, // 是否可以滑动
  6. this.padding,
  7. this.indicatorColor,// 指示器颜色,默认是高度为2的一条下划线
  8. this.automaticIndicatorColorAdjustment = true,
  9. this.indicatorWeight = 2.0,// 指示器高度
  10. this.indicatorPadding = EdgeInsets.zero, //指示器padding
  11. this.indicator, // 指示器
  12. this.indicatorSize, // 指示器长度,有两个可选值,一个tab的长度,一个是label长度
  13. this.labelColor,
  14. this.labelStyle,
  15. this.labelPadding,
  16. this.unselectedLabelColor,
  17. this.unselectedLabelStyle,
  18. this.mouseCursor,
  19. this.onTap,
  20. ...
  21. })

TabBar 通常位于 AppBar 的底部,它也可以接收一个 TabController ,如果需要和 TabBarView 联动, TabBar 和 TabBarView 使用同一个 TabController 即可,注意,联动时 TabBar 和 TabBarView 的孩子数量需要一致。如果没有指定 controller,则会在组件树中向上查找并使用最近的一个 DefaultTabController 。另外我们需要创建需要的 tab 并通过 tabs 传给 TabBar, tab 可以是任何 Widget,不过Material 组件库中已经实现了一个 Tab 组件,我们一般都会直接使用它:

  1. const Tab({
  2. Key? key,
  3. this.text, //文本
  4. this.icon, // 图标
  5. this.iconMargin = const EdgeInsets.only(bottom: 10.0),
  6. this.height,
  7. this.child, // 自定义 widget
  8. })

注意,textchild 是互斥的,不能同时制定。 

实例代码:

  1. import 'package:flutter/material.dart';
  2. /// @Author wywinstonwy
  3. /// @Date 2022/1/18 9:09 上午
  4. /// @Description:
  5. class MyTabbarView1 extends StatefulWidget {
  6. const MyTabbarView1({Key? key}) : super(key: key);
  7. @override
  8. _MyTabbarView1State createState() => _MyTabbarView1State();
  9. }
  10. class _MyTabbarView1State extends State<MyTabbarView1>with SingleTickerProviderStateMixin {
  11. List<String> tabs =['新闻','历史','图片'];
  12. late TabController tabController;
  13. @override
  14. void initState() {
  15. // TODO: implement initState
  16. super.initState();
  17. tabController = TabController(length: tabs.length, vsync: this);
  18. }
  19. @override
  20. Widget build(BuildContext context) {
  21. return Scaffold(
  22. appBar: AppBar(
  23. title: Text('TabbarView',textAlign: TextAlign.center,),
  24. bottom:TabBar(
  25. unselectedLabelColor: Colors.white.withOpacity(0.5),
  26. labelColor: Colors.white,
  27. indicatorSize:TabBarIndicatorSize.label,
  28. indicator:const UnderlineTabIndicator(),
  29. controller: tabController,
  30. tabs: tabs.map((e){
  31. return Tab(text: e,);
  32. }).toList()) ,
  33. ),
  34. body: Column(
  35. children: [
  36. Expanded(
  37. flex: 1,
  38. child: TabBarView(
  39. controller: tabController,
  40. children: tabs.map((e){
  41. return Center(child: Text(e,style: TextStyle(fontSize: 100),),);
  42. }).toList()),)
  43. ],),
  44. );
  45. }
  46. }

 

滑动页面时顶部的 Tab 也会跟着动,点击顶部 Tab 时页面也会跟着切换。为了实现 TabBar 和 TabBarView 的联动,我们显式创建了一个 TabController,由于 TabController 又需要一个 TickerProvider (vsync 参数), 我们又混入了 SingleTickerProviderStateMixin;由于 TabController 中会执行动画,持有一些资源,所以我们在页面销毁时必须得释放资源(dispose)。综上,我们发现创建 TabController 的过程还是比较复杂,实战中,如果需要 TabBar 和 TabBarView 联动,通常会创建一个 DefaultTabController 作为它们共同的父级组件,这样它们在执行时就会从组件树向上查找,都会使用我们指定的这个 DefaultTabController。我们修改后的实现如下: 

  1. class TabViewRoute2 extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. List tabs = ["新闻", "历史", "图片"];
  5. return DefaultTabController(
  6. length: tabs.length,
  7. child: Scaffold(
  8. appBar: AppBar(
  9. title: Text("App Name"),
  10. bottom: TabBar(
  11. tabs: tabs.map((e) => Tab(text: e)).toList(),
  12. ),
  13. ),
  14. body: TabBarView( //构建
  15. children: tabs.map((e) {
  16. return KeepAliveWrapper(
  17. child: Container(
  18. alignment: Alignment.center,
  19. child: Text(e, textScaleFactor: 5),
  20. ),
  21. );
  22. }).toList(),
  23. ),
  24. ),
  25. );
  26. }
  27. }

可以看到我们无需去手动管理 Controller 的生命周期,也不需要提供 SingleTickerProviderStateMixin,同时也没有其它的状态需要管理,也就不需要用 StatefulWidget 了,这样简单很多。

页面缓存

因为TabBarView 内部封装了 PageView,如果要缓存页面,可以参考 PageView 一节中关于页面缓存的介绍。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/431827
推荐阅读
相关标签
  

闽ICP备14008679号