TabController 构造函数中的 `vsync` 属性

`vsync` property in TabController constructor

据此:sample code

我创建了自己的 TabController 实现:

void main() {
  runApp(new MyApp());
}

class MyApp extends StatefulWidget {

  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = new TabController(vsync: this, length: choices.length);
  }

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

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        bottomNavigationBar: new Material(
          color: Colors.blue,
          child: new TabBar(
            controller: _tabController,
            isScrollable: false,
            tabs: choices.map((Choice choice) {
              return new Tab(
                text: null,
                icon: new Icon(choice.icon),
              );
            }).toList(),
          ),
        ),
        appBar: new AppBar(
          title: const Text('Swap'),
        ),
        body: new TabBarView(
          controller: _tabController,
          children: choices.map((Choice choice) {
            return new Padding(
              padding: const EdgeInsets.all(16.0),
              child: new ChoiceCard(choice: choice),
            );
          }).toList(),
        ),
      ),
    );
  }
}

在线:_tabController = new TabController(vsync: this, length: choices.length); 我收到错误消息:

error: The argument type '_MyAppState' can't be assigned to the parameter type 'TickerProvider'. (argument_type_not_assignable at [swap] lib/main.dart:24)

我的代码有什么问题?

with TickerProviderStateMixin 添加到 State 的 class 声明的末尾。

如前所述,添加 mixinTickerProviderStateMixin 应该可以完成工作,或者如果您只需要一个 Ticker,也可以使用 SingleTickerProviderStateMixin ].

But what is Does TickerProviders really do?

vsyncTickerProvider 作为参数,这就是我们使用 SingleTickerProviderStateMixin 的原因,正如名称描述的那样,TickerProvider 提供了 Ticker,这就是它的意思告诉我们的应用程序有关帧更新(或屏幕更新)的信息,以便我们的 AnimationController 可以生成新值并且我们可以重绘动画小部件。

只需在extends状态class末尾添加with TickerProviderStateMixin如下:

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
//...
}

在语句末尾添加任何这些 SingleTickerProviderStateMixin/ TickerProviderStateMixin mixins,如下所示:

例如:

class _ListingViewState extends State with SingleTickerProviderStateMixin { }

你所要做的就是添加到这个 - SingleTickerProviderStateMixin 旁边 State<MyApp> 正如@Shubham-Soni 上面所说

只需更改此行:

_MyAppState extends State<MyApp>

为此:

_MyAppState extends State<MyApp>
    with SingleTickerProviderStateMixin

这是如何执行此操作的完整示例

class MyApp extends StatefulWidget {

  const MyApp({Key key}) : super(key: key);
  @override
  _MyAppState createState() => _MyAppState();

}

class _MyAppState extends State<MyApp>
    with SingleTickerProviderStateMixin {

  TabController tabController;

  void initState() {
    tabController =
        TabController(length: tabsList.length, vsync: this, initialIndex: 0);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    throw UnimplementedError();
  }
}

问题很笼统,需要详细描述

垂直同步用于

  • vsync 是代表 TickerProvider 的 属性(即 Tick 类似于时钟的滴答声,这意味着在每个特定的持续时间 TickerProvider 将呈现 class 状态并重绘对象。)

  • vsync 属性 仅在需要渲染其 class 状态的构造函数上才需要重绘并反映 UI.

  • vsync 可以与 classes 一起使用,需要特定的过渡或动画来重新渲染以绘制不同的对象。

内部实现

TabController({ int initialIndex = 0, @required this.length, @required TickerProvider vsync })
: assert(length != null && length >= 0),
  assert(initialIndex != null && initialIndex >= 0 && (length == 0 || initialIndex < length)),
  _index = initialIndex,
  _previousIndex = initialIndex,
  _animationController = AnimationController.unbounded(
    value: initialIndex.toDouble(),
    vsync: vsync,
  );

TabController 在内部使用 AnimationController 来呈现标签栏状态

在class状态

末尾添加TickerProviderStateMixin

这是完整的例子

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with TickerProviderStateMixin {
  MotionTabController? _tabController;
  @override
  void initState() {
    super.initState();
    _tabController = new MotionTabController(initialIndex: 1, vsync: this);
  }

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

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    throw UnimplementedError();
  }
}

在 GetX 中

我找到了一个解决方案,只需添加 SingleGetTickerProviderMixin 即可成为完整代码,如下所示:

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

class ControllerViewModel extends GetxController with SingleGetTickerProviderMixin {
  AnimationController _controller;
  @override
  void onInit() {
    // TODO: implement onInit
    super.onInit();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(
        milliseconds: 2500,
      ),
    );
  }
}

上面的答案是正确的,但你必须在 class 中声明一个标签栏并从 iniState 初始化标签栏,否则 vsync 变量不接受 'this ' 以下代码可能对您有所帮助。

class _MatchesState extends State<Matches> with SingleTickerProviderStateMixin {
  TabController? tabController;
  @override
  void initState() {
    tabController = TabController(
      length: 2,
      vsync: this,
      initialIndex: 0,
    );
    super.initState();
  }