如何将 ColorTween 动画添加到 TabBar?

问题描述 投票:0回答:4

我正在制作标签之间的简单彩色孪生动画

应该是这样的

我认为我接近正确的解决方案,但是当我在 Tab3 上切换时,没有任何效果

在每个选项卡中我都有一个

Animation<color>
但我不知道如何声明为新选项卡,或者当我擦到新选项卡并设置新选项卡
ColorTween()
请帮助我,我不知道我是否应该为这 3 个选项卡创建一个新的 AnimationController 或只创建一个
Animation<color>

这里是选项卡中动画的一些代码

 @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(() {} ); });
    }

  }

和完整代码

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,
                ),
              ]
          ),
        )
      ],
    );

  }
}
flutter flutter-animation
4个回答
1
投票

我解决了这个问题

我没有给 TabBar 添加新的动画。 我在 tabcontroller 中使用 Animation.value

颜色值在选项卡中获取

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

来自 tabController 和当前选项卡的不透明度值

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;

  }

1
投票

感谢您的解决方案FloW

这是对您的

getCurrClr()
功能的改进:

// returns opacity [0.0 .. 1.0] for a tab using animation value and tab index
double getCurrClr() {
  final value = tabcontroller.animation!.value;
  
  if (tabindex == 0 && value < 1) {
    return 1 - value;
  } else if (value <= tabindex && value > tabindex - 1) {
    return value - (tabindex - 1);
  } else if (value > tabindex && value < tabindex + 1) {
    return (tabindex + 1) - value;
  }
  
  return 0.0;
}

这将适用于任意数量的选项卡,无论是三个选项卡还是 15 个选项卡。


0
投票

试试这个

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

class PyWidgetTestPage extends StatefulWidget {
  PyWidgetTestPage({Key key, routerArguments}) : super(key: key);
  @override
  _PyWidgetTestPageState createState() => _PyWidgetTestPageState();
}

class _PyWidgetTestPageState extends State<PyWidgetTestPage> with TickerProviderStateMixin {
  TabController controller; //= TabController(length: 14, vsync: this);
  AnimationController anicontroller;
  Animation animation;
  Animation<int> intAnim;
  Animation<Color> colorAni;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = TabController(length: 14, vsync: this);
    ;
    // ColorTween(
    // //   begin: Colors.black26,
    // //   end: new Color(0xff622F74),
    // // ).animate(_conrtoller)
    // //   ..addListener(() {
    // //     print("set stats");
    // //     setState(() {});
    // //   });
    // // _conrtoller.forward();
    // anicontroller = AnimationController(duration: const Duration(milliseconds: 10000), vsync: this);
    // anicontroller.addListener(() {
    //   print("controller=====${anicontroller.value}");
    // });
    // anicontroller.addStatusListener((status) {
    //   print("status====$status");
    // });
    // intAnim = IntTween(begin: 0, end: 200).animate(anicontroller)
    //   ..addListener(() {
    //     setState(() {});
    //   })
    //   ..addStatusListener((status) {});
    // // colorAni = ColorTween(begin: Colors.purpleAccent, end: Colors.orange).animate(anicontroller)
    // //   ..addListener(() {
    // //     setState(() {});
    // //   })
    // //   ..addStatusListener((status) {});
    // anicontroller.forward();
  }

  @override
  Widget build(BuildContext context) {
    // return Scaffold(
    //   appBar: new AppBar(
    //     backgroundColor: colorAni?.value ?? Colors.purple,
    //     title: new Text("adfadf"),
    //   ),
    //   body: Column(children: [
    //     Text("${intAnim?.value ?? "ssss"}"),
    //   ]),
    // );
    return TabAnimation();
  }
}

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

class _TabAnimationState extends State<TabAnimation> with TickerProviderStateMixin {
  TabController _tabController;
  GlobalKey<__TabState> keyA = GlobalKey();
  GlobalKey<__TabState> keyB = GlobalKey();
  GlobalKey<__TabState> keyC = GlobalKey();

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

  @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("${Icons.animation}"),
            bottom: new PreferredSize(
              preferredSize: const Size(double.infinity, 48.0),
              child: new Container(
                color: Colors.white,
                child: new TabBar(
                  onTap: (int value) {
                    print("adfadf $value");
                    keyA.currentState.setAnimation(value == 0); //调用子控件方法
                    keyB.currentState.setAnimation(value == 1); //调用子控件方法
                    keyC.currentState.setAnimation(value == 2); //调用子控件方法
                  },
                  labelColor: Colors.black87,
                  unselectedLabelColor: Colors.grey,
                  controller: _tabController,
                  tabs: <Widget>[
                    Tab(
                        child: new _Tab(
                      0,
                      "Tab1",
                      _tabController,
                      key: keyA,
                    )),
                    Tab(
                        child: new _Tab(
                      1,
                      "Tab2",
                      _tabController,
                      key: keyB,
                    )),
                    Tab(
                        child: new _Tab(
                      2,
                      "Tab3",
                      _tabController,
                      key: keyC,
                    )),
                  ],
                ),
              ),
            ),
          ),
          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> with TickerProviderStateMixin {
  int count;
  bool isSelected;
  Animation<Color> animation;
  AnimationController _conrtoller; // = AnimationController(duration: Duration(milliseconds: 300), vsync: this);
  @override
  void initState() {
    super.initState();
    _conrtoller = AnimationController(duration: Duration(milliseconds: 300), vsync: this);
    ;
    isSelected = widget.tabindex == 0;
    setAnimation(widget.tabindex == 0);
  }

  setAnimation(bool selected) {
    if (isSelected == selected) {
      return;
    }
    isSelected = selected;
    print("widget index ${widget.tabindex} selectedc: $selected");
    _conrtoller?.dispose();
    _conrtoller = AnimationController(duration: Duration(milliseconds: 300), vsync: this);
    animation = ColorTween(
      begin: selected ? Colors.black26 : new Color(0xff622F74),
      end: selected ? new Color(0xff622F74) : Colors.black26,
    ).animate(_conrtoller)
      ..addListener(() {
        print("set stats");
        setState(() {});
      });
    _conrtoller.forward();
  }

  @override
  Widget build(BuildContext context) {
    print("build${widget.tabindex}");
    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,
                ),
              ]),
        )
      ],
    );
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.