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

Posted

技术标签:

【中文标题】TabController 构造函数中的 `vsync` 属性【英文标题】:`vsync` property in TabController constructor 【发布时间】:2018-04-01 18:02:37 【问题描述】:

据此: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); 我收到错误消息:

错误:无法将参数类型“_MyAppState”分配给参数类型“TickerProvider”。 (argument_type_not_assignable 在 [swap] lib/main.dart:24)

我的代码有什么问题?

【问题讨论】:

【参考方案1】:

在类状态末尾添加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();
  

【讨论】:

【参考方案2】:

问题很笼统,需要多描述一下

垂直同步用于

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

只有当我们需要渲染我们的组件或小部件以重绘和反映 UI 时,需要在每个特定偏移时间渲染其类状态的构造函数才需要 vsync 属性。

vsync 可以与需要某些过渡或动画重新渲染以绘制不同对象的类一起使用。

内部实现

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 来呈现标签栏状态

【讨论】:

它看起来真的可能是一个可选参数。【参考方案3】:

你所要做的就是添加到这个 - SingleTickerProviderStateMixin 旁边 State&lt;MyApp&gt; 正如@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();
  

【讨论】:

【参考方案4】:

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

例如:

class _ListingViewState 使用 SingleTickerProviderStateMixin

扩展 State

【讨论】:

【参考方案5】:

只需在extends状态类的末尾添加with TickerProviderStateMixin,如下:

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

【讨论】:

【参考方案6】:

正如前面回答的那样,添加 mixinTickerProviderStateMixin 应该可以完成这项工作,或者如果您只需要单个 Ticker,您也可以使用 SingleTickerProviderStateMixin

但是TickerProviders 真的是做什么的呢?

vsyncTickerProvider 作为参数,这就是我们使用SingleTickerProviderStateMixin 的原因,正如名称所描述的,TickerProvider 提供Ticker,这仅仅意味着它告诉我们的应用程序有关框架更新(或屏幕更新) , 这样我们的AnimationController 就可以生成一个新的值,我们可以重新绘制动画小部件。

【讨论】:

【参考方案7】:

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

【讨论】:

就是这样。现在我在更改选项卡期间登录控制台很奇怪:Another exception was thrown: 'package:flutter/src/rendering/object.dart': Failed assertion: line 2257 pos 12: 'fragment is _InterestingSemanticsFragment': is not true. 听起来不相关,也许重启应用/升级你的 Flutter? 使用 StateMixin 可能会遇到热重载问题,如果这样做,请尝试使用 TickerProviderStateMixin 而不是 SingleTickerProviderStateMixin

以上是关于TabController 构造函数中的 `vsync` 属性的主要内容,如果未能解决你的问题,请参考以下文章

如何在另一个 TabController 中选择 ViewController?

不能在vsi2017的linux子系统中包含头文件

python 获取VSI GPU

python 为VSI获取带宽

TabController定义顶部tab切换

Flutter(十六):TabController