Getx在Controller里添加TabController的处理

  • Post author:
  • Post category:其他


因为SingleTickerProviderStateMixin都是限制在State上使用的。这个可以看下源码:

而TabController实例化里面有个参数vsync 是需要在StatefulWidget的state上with SingleTickerProviderStateMixin才能获取符合vsync实例。因此提出两个问题:

一、请问下用了getx的话要怎么使用tabController之类的需要withSingleTickerProviderStateMixin的View呢?

答:如果不考虑tabView监听的话,可以用DefaultTabController。

二、假如我又需要自己控制TabController呢,DefaultTabController不能监听到tab的点击处理事件,咋办?

答:用getx的controller里添加GetSingleTickerProviderStateMixin

正好因为项目中遇到这个问题,网上搜了下,不少同学也遇到了。比如


小呆呆666

的文章

《Flutter GetX使用—简洁的魅力》

有同学就提出此疑问,

另外我在stackoverflow上也看到老外也有位同学碰到这个问题,


How to build a TabView using Flutter GetX

其实处理方式也很简单,getx提供了GetSingleTickerProviderStateMixin去处理tabBarView的tab点击监听事件的。在自定义Controller的时候继承GetxController,同时with GetSingleTickerProviderStateMixin就能达到需求。例如:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class MyTabController extends GetxController
    with GetSingleTickerProviderStateMixin {
  final List<Tab> myTabs = <Tab>[
    Tab(text: '第一个tab'),
    Tab(text: '第二个tab'),
  ];

  TabController? tabController;

  @override
  void onInit() {
    super.onInit();
    tabController = TabController(vsync: this, length: myTabs.length);
    tabController?.addListener(() {
      ///避免addListener调用2次
      if (tabController?.index == tabController?.animation?.value) {
        print("点击了下标为${tabController?.index}的tab");
      }
    });
  }

  @override
  void onClose() {
    tabController?.dispose();
    super.onClose();
  }
}

其实处理方法和在StatefulWidget里的state里一样,无非一个是在widget里,一个在Controller里。可以对比下:

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin{}

最后就是在widget,也就是view层调用就行了:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test_demo/MyTabController.dart';
import 'package:get/get.dart';

///author:331209
///Time:2022/8/8
///description:
class MyTabView extends StatelessWidget {
  MyTabController controller = Get.put(MyTabController());
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("tabview"),
          bottom: TabBar(
            controller: controller.tabController,
            tabs: controller.myTabs,
          ),
        ),
        body: TabBarView(
          controller: controller.tabController,
          children: controller.myTabs.map((Tab tab) {
            final String label = tab.text!.toLowerCase();
            return Center(
              child: Text(
                ' $label ',
                style: const TextStyle(fontSize: 36),
              ),
            );
          }).toList(),
        ));
  }
}

其实就是getx官网没给出具体的方案说明而已或者一般比较难找到此实现方案,导致很多同学想着在外层包层StatefulWidget来处理TabController,细思极恐,如果这样操作的话,就简单问题复杂化了。



版权声明:本文为csj731742019原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。