87

According to this: sample code

I created my own implementation of 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(),
        ),
      ),
    );
  }
}

In line: _tabController = new TabController(vsync: this, length: choices.length); I got error this message:

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

What is wrong with my code?

marktani
  • 7,578
  • 6
  • 37
  • 60
Kamil Harasimowicz
  • 4,684
  • 5
  • 32
  • 58

9 Answers9

169

Add with TickerProviderStateMixin to the end of your State’s class declaration.

Collin Jackson
  • 110,240
  • 31
  • 221
  • 152
  • It was that. Now Im getting weird log in console during changing tabs: `Another exception was thrown: 'package:flutter/src/rendering/object.dart': Failed assertion: line 2257 pos 12: 'fragment is _InterestingSemanticsFragment': is not true.` – Kamil Harasimowicz Oct 20 '17 at 14:35
  • Doesn’t sound related, maybe restart app / upgrade your Flutter? – Collin Jackson Oct 20 '17 at 14:36
  • You might get hot Reload issues using StateMixin, if you do, try to use TickerProviderStateMixin instead of SingleTickerProviderStateMixin – Ruan Apr 19 '20 at 10:35
40

Simply add with TickerProviderStateMixin at the end of extends state class as follows:

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
//...
}
Alireza Rahmani Khalili
  • 2,727
  • 2
  • 32
  • 33
Harsh Kumar
  • 501
  • 4
  • 4
19

As Answered earlier adding the mixin, TickerProviderStateMixin should do the job or you can also use SingleTickerProviderStateMixin if you only need a Single Ticker.

But what is Does TickerProviders really do?

vsync takes a TickerProvider as an argument , that's why we use SingleTickerProviderStateMixin and as the named describes TickerProvider provides Ticker which simply means it tells our app about the Frame update(or Screen Update), so that our AnimationController can generate a new value and we can redraw the animated widget.

Shubhamhackz
  • 7,333
  • 7
  • 50
  • 71
10

Add TickerProviderStateMixin at the end of class state

Here is the full example

  @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();
  }
}
dhaval_nakum
  • 210
  • 3
  • 6
8

Question is very generic, so need to describe more

Vsync used for

  • vsync is the property that represents the TickerProvider (i.e., Tick is similar to clock's tick which means that at every certain duration TickerProvider will render the class state and redraw the object.)

  • vsync property is required only on that constructor which requires to render its class state at every certain off-set time when we need to render our components or widgets to redraw and reflect the UI.

  • vsync can be used with the classes which require certain transition or animation to re-render to draw different objects.

Internal Implementation

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 uses AnimationController internally for the rendering of the tab bar state

Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
7

In GetX

I found a solution just add with SingleGetTickerProviderMixin to be the full code as the below one:

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

class ControllerViewModel extends GetxController with GetSingleTickerProviderStateMixin {
  AnimationController _controller;
  @override
  void onInit() {
    // TODO: implement onInit
    super.onInit();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(
        milliseconds: 2500,
      ),
    );
  }
}
Abdelrahman Tareq
  • 1,874
  • 3
  • 17
  • 32
Jithin U. Ahmed
  • 1,495
  • 1
  • 19
  • 29
6

The above answers are correct but you have to declare a tabbar in class and initialize the tabbar from iniState, else the vsync variable doesn't accept 'this' Following code may help you.

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

Add any of these SingleTickerProviderStateMixin/ TickerProviderStateMixin mixins at the end of the statement like below:

Eg:

class _ListingViewState extends State with SingleTickerProviderStateMixin { }

rohit
  • 1
  • 1
0

just extend with SingleTickerProviderStateMixin in class you can see here full code

enter image description here