当前位置:   article > 正文

Flutter:TabController简单协调TabBar与TabView

flutter tabcontroller
简单 demo

  1. class _RankPageState extends State<RankPage>{
  2. final List<Tab> titleTabs = <Tab>[
  3. Tab(
  4. text: '今日实时榜',
  5. ),
  6. Tab(
  7. text: '昨日排行榜',
  8. ),
  9. Tab(
  10. text: '上周积分榜',
  11. ),
  12. ];
  13. ...
  14. child: Scaffold(
  15. appBar: AppBar(
  16. ...
  17. elevation: 0.0,
  18. backgroundColor: Color.fromRGBO(26, 172, 255, 1),
  19. title: TabBar(
  20. isScrollable: true,
  21. indicator: UnderlineTabIndicator(
  22. borderSide: BorderSide(style: BorderStyle.none)),
  23. tabs: titleTabs
  24. ),
  25. ),
  26. body: Container(
  27. color: Color.fromRGBO(26, 172, 255, 1),
  28. child: TabBarView(
  29. //TabBarView 默认支持手势滑动,若要禁止设置 NeverScrollableScrollPhysics
  30. physics: NeverScrollableScrollPhysics(),
  31. children: <Widget>[
  32. Center(child:Text('view1')),
  33. Center(child:Text('view2')),
  34. Center(child:Text('view3')),
  35. ],
  36. ),
  37. ),
  38. ),
  39. ...
  40. }
  41. 复制代码

TabBar与TabBarView通过index有一一对应关系,并且默认提供了DefaultTabController建立两者之间的关系,若要切换动画以及监听切换交互,可以自定义一个 Controller

  1. class _RankPageState extends State<RankPage> with SingleTickerProviderStateMixin{
  2. ...
  3. TabController tabController;
  4. @override
  5. void initState() {
  6. super.initState();
  7. // 添加监听器
  8. tabController = TabController(vsync: this, length: titleTabs.length)
  9. ..addListener(() {
  10. switch (tabController.index) {
  11. case 0:
  12. print(1);
  13. break;
  14. case 1:
  15. print(2)
  16. break;
  17. case 2:
  18. print(3)
  19. break;
  20. }
  21. });
  22. }
  23. ...
  24. //增加controller
  25. title: TabBar(
  26. controller: tabController,
  27. ...
  28. )
  29. ...
  30. child: TabBarView(
  31. controller: tabController,
  32. ...
  33. )
  34. ...
  35. }
  36. 复制代码

运行之后查看结果,每次切换 tab 控制台都会打印相应的值,但有个问题,点击选项卡切换时打印了2次,似乎执行了两遍,滑动切换时正常输出一次。
原因大致是因为: 点击时 在动画过程先后触发了 notifyListeners();
源码如下:

相关详细问题-Github Issues

看一下 TabController Class API,有以下属性

  1. //该动画值表示当前TabBar选中的指示器位置以及TabBar和TabBarView的scrollOffsets
  2. animation → Animation<double>
  3. //当前选中Tab的下标。改变index也会更新 previousIndex、设置animation's的value值、重置indexIsChanging为false并且通知监听器
  4. index ↔ int
  5. //true:当动画从上一个跳到下一个时
  6. indexIsChanging → bool
  7. //tabs的总数,通常大于1
  8. length → int
  9. //不同于animation's的value和index。offset value必须在-1.0和1.0之间
  10. offset ↔ double
  11. //上一个选中tab的index值,最初与index相同
  12. previousIndex → int
  13. 复制代码

那么我们可以加一层判断在监听器中

  1. ...
  2. tabController = TabController(vsync: this, length: titleTabs.length)
  3. ..addListener(() {
  4. if(tabController.indexIsChanging){
  5. switch (tabController.index) {
  6. case 0:
  7. print(1);
  8. break;
  9. case 1:
  10. print(2)
  11. break;
  12. case 2:
  13. print(3)
  14. break;
  15. }
  16. }
  17. });
  18. ...
  19. 复制代码

以上解决了点击执行两次代码块的问题,但试试滑动的时候,indexIsChanging一直都是false,也就是说滑动切换无法执行我们的代码。。。。
摸索调试了一番,为了让滑动和点击都执行我们的代码块且只有一次,做如下改动

  1. ...
  2. tabController = TabController(vsync: this, length: titleTabs.length)
  3. ..addListener(() {
  4. if(tabController.index.toDouble() == tabController.animation.value){
  5. switch (tabController.index) {
  6. case 0:
  7. print(1);
  8. break;
  9. case 1:
  10. print(2)
  11. break;
  12. case 2:
  13. print(3)
  14. break;
  15. }
  16. }
  17. });
  18. ...
  19. 复制代码

恩~~~解决我们的需求了。。。

参考

官方TabController API

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

闽ICP备14008679号