Search code examples
flutterflutter-animation

How to add a ColorTween Animation to a TabBar?


I'm working on a simple Color Twin Animation between the Tabs

it should looking like this

enter image description here

i think i am near at a right solution, but when i tab on Tab3 nothing works fine

in each Tab i have a Animation<color> but i don't know how can i declare as a new one, or when i wipe to the new tab and set a new ColorTween() Please help me, i don't know if i should create a new AnimationController or maybe only one Animation<color> for this 3 Tab's

here is some code of the Animation in the Tab

 @override
  void initState() {
    super.initState();

    setAnimation();

  }

  setAnimation() {

    if (widget.tabcontroller.animation.value == widget.tabindex ||
        widget.tabcontroller.animation.value + 1 == widget.tabindex ||
        widget.tabcontroller.animation.value - 1 == widget.tabindex) {

      // set animation in which direction
      animation = ColorTween(
        begin: widget.tabcontroller.animation.value == widget.tabindex ? new Color(0xff622F74) : Colors.black26,
        end: widget.tabcontroller.animation.value == widget.tabindex ? Colors.black26 : new Color(0xff622F74),
      ).animate(widget.tabcontroller.animation)
        ..addListener(() { setState(() {} ); });
    }

  }

and the full code

class TabAnimation extends StatefulWidget {
  @override
  _TabAnimationState createState() => _TabAnimationState();
}

class _TabAnimationState extends State<TabAnimation> with TickerProviderStateMixin {

  TabController _tabController;

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Colors.lightBlue,
        accentColor: Colors.orange,
      ),
      home: DefaultTabController(
        length: 3,
        child: new Scaffold(
          appBar: new AppBar(
            title: new Text("TabAnimatedColorTween"),
            bottom: new PreferredSize(
              preferredSize: const Size(double.infinity, 48.0),
              child : new Container(
                color: Colors.white,
                child: new TabBar(
                  labelColor: Colors.black87,
                  unselectedLabelColor: Colors.grey,
                  controller: _tabController,
                  tabs: <Widget>[
                    Tab(child: new _Tab(0, "Tab1", _tabController)),
                    Tab(child: new _Tab(1, "Tab2", _tabController)),
                    Tab(child: new _Tab(2, "Tab3", _tabController)),
                  ],
                ),
              ),
            ),
          ),
          body: TabBarView(
            controller: _tabController,
            children: <Widget>[
              new Container(child: Center(child: new Text("1"))),
              new Container(child: Center(child: new Text("2"))),
              new Container(child: Center(child: new Text("3"))),
            ],
          ),
        ),
      ),
    );
  }
}



class _Tab extends StatefulWidget {
  final int tabindex;
  final String tabname;
  final TabController tabcontroller;

  _Tab(this.tabindex, this.tabname, this.tabcontroller, {Key key}) : super(key: key);

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

class __TabState extends State<_Tab> {

  int count;
  Animation<Color> animation;

  @override
  void initState() {
    super.initState();

    setAnimation();

  }

  setAnimation() {

    if (widget.tabcontroller.animation.value == widget.tabindex ||
        widget.tabcontroller.animation.value + 1 == widget.tabindex ||
        widget.tabcontroller.animation.value - 1 == widget.tabindex) {

      // set animation in which direction
      animation = ColorTween(
        begin: widget.tabcontroller.animation.value == widget.tabindex ? new Color(0xff622F74) : Colors.black26,
        end: widget.tabcontroller.animation.value == widget.tabindex ? Colors.black26 : new Color(0xff622F74),
      ).animate(widget.tabcontroller.animation)
        ..addListener(() { setState(() {} ); });
    }

  }


  @override
  Widget build(BuildContext context) {

    return new Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        new Text(widget.tabname),
        new Container(
          alignment: AlignmentDirectional.center,
          constraints: BoxConstraints(minHeight: 22.0, minWidth: 22.0),
          margin: EdgeInsets.only(left: 5.0),
          child: new Text(widget.tabindex.toString(), style: TextStyle(color: Colors.white70, fontSize: 10.0),),
          decoration: new BoxDecoration(
              shape: BoxShape.circle,
              color: animation == null ? Colors.black26 : animation.value,
              border: new Border.all(
                width: 0.8,
                color: Colors.white,
              ),
              boxShadow: [
                new BoxShadow(
                  color: Colors.black.withOpacity(0.4),
                  blurRadius: 5.0,
                ),
              ]
          ),
        )
      ],
    );

  }
}

Solution

  • i solve this problem

    i did not add a new Animation to the TabBar. i work with the Animation.value in the tabcontroller

    Color value get in the Tab

    color: Theme.of(context).primaryColor.withOpacity(getCurrClr()),
    

    Opacity value from the tabController and current tab

    double getCurrClr() {
    
        if(tabindex==0 && tabcontroller.animation.value < 1)
          return 1 - tabcontroller.animation.value;
    
        if(tabindex==1 && tabcontroller.animation.value <= 1)
          return tabcontroller.animation.value;
    
        if(tabindex==1 && tabcontroller.animation.value > 1)
          return 2 - tabcontroller.animation.value;
    
        if(tabindex==2 && tabcontroller.animation.value <= 2 && tabcontroller.animation.value > 1)
          return tabcontroller.animation.value - 1;
    
        return 0.0;
    
      }