因为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,细思极恐,如果这样操作的话,就简单问题复杂化了。