栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Flutter:英雄过渡+小部件动画同时出现?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Flutter:英雄过渡+小部件动画同时出现?

我做过类似的事情,但是不幸的是我的代码还包含很多其他内容,而且要做起来相对繁琐,所以我不得不将它们分解成一个例子,这比我现在能做的要多。我将解释我所做的一般概念。也许还有更好的方法可以做到这一点。

您想编写一个StatefulWidget,其State也扩展了NavigatorObserver(您可以使用无状态的widget,但我认为不是)。我个人将其放置在树中导航器的上方(即,它在其“
build”功能中构建了导航器),但是您很可能也将其置于“导航器”的旁边。

覆盖NavigatorObserver中的didPush,didRemove,didPop等方法。在其中的每一个中,调用setState并保存动画和其他参数,如下所示:

class NavigationFaderState extends State<NavigationFader> with NavigatorObserver {  Animation _animation;  // whatever else you need, maybe starting/finishing opacity or position etc.  @override  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {    setState(() {      _animation = route.animation;    }    route.animation.addStatusListener((status) {      if (status = AnimationStatus.completed) {        setState(() {          _animation = null;        });      }    });  }  ....}

在您的构建函数中,您需要根据_animation和animate以及是否可能要设置的其他参数(例如,是否要进行动画处理的标志以及前进或后退的标志)进行检查-
我相信“
pop”动画已从0开始并与推入动画一样升至1,但我可能错了)。然后,您可以将该动画连接到想要设置导航栏动画的位置,可以使用AnimatedBuilder或直接将动画连接起来,等等。如果有关于这一切工作方式的任何特定问题,请发表评论,我将添加一些评论,等等。

希望有帮助=)

编辑:完整的代码示例。作为记录,我不建议这段代码那么好,或者您应该这样做。但这是解决问题的一种方法。在实际应用中使用它之前,值得对其进行测试,并可能添加一些断言以检查状态等。

导入’package:flutter / material.dart’;

void main() => runApp(new MyApp());class MyApp extends StatelessWidget {  PushListener listener = new PushListener();  @override  Widget build(BuildContext context) {    return new WidgetsApp(      locale: new Locale("en"),      navigatorObservers: [listener],      builder: (context, child) {        // this is here rather than outside the WidgetsApp so that it        // gets access to directionality, text styles, etc        return new Scaffold(          body: child,          bottomNavigationBar:   new ColorChangingNavigationBar(key: listener.navBarKey),        );      },      onGenerateRoute: (settings) {        switch (settings.name) {          case '/': return new MaterialPageRoute(   settings: settings,   builder: (context) => Column(         children: <Widget>[new Text(    "I have a green nav bar when you open me and blue when you come back"),new RaisedButton(  onPressed: () {    Navigator.pushNamed(context, "/red");  },  child: new Text("Next"),),         ],       ), );          case '/red': return new MaterialPageRoute(   settings: settings,   builder: (context) => Column(         children: <Widget>[new Text("I have a red nav bar"),new RaisedButton(  onPressed: () {    Navigator.pop(context);  },)         ],       ), );        }      },      color: Colors.blue,    );  }}class PushListener extends NavigatorObserver {  GlobalKey<ColorChangingNavigationBarState> navBarKey = new GlobalKey();  @override  void didPop(Route route, Route previousRoute) {    if (route is ModalRoute && navBarKey.currentState != null) {      var name = route.settings.name;      var color = name == "/" ? Colors.red.shade500 : Colors.blue.shade500;      var animation = new ReverseAnimation(route.animation);      print("Popping & changing color to: ${name == "/" ? "red" : "blue"}");      navBarKey.currentState.setAnimating(animation, color);    }  }  @override  void didPush(Route route, Route previousRoute) {    if (route is ModalRoute && navBarKey.currentState != null) {      var name = route.settings.name;      var color = name == "/" ? Colors.blue.shade500 : Colors.red.shade500;      print("Pushing & changing color to: ${name == "/" ? "red" : "blue"}");      var animation = route.animation;      navBarKey.currentState.setAnimating(animation, color);    }  }  @override  void didRemove(Route route, Route previousRoute) {    // probably don't need  }  @override  void didStartUserGesture() {    // might want to do if gestures are supported with whichever type of    // route you're using.  }  @override  void didStopUserGesture() {    // if you implement didStartUserGesture  }}class ColorChangingNavigationBar extends StatefulWidget {  final Color startColor;  ColorChangingNavigationBar(      {Key key, this.startColor = const Color.fromRGBO(0, 255, 0, 1.0)})      : super(key: key);  @override  State<StatefulWidget> createState() => new ColorChangingNavigationBarState();}class _ColorAnimationInfo {  final Animation animation;  final Tween<Color> colorTween;  final AnimationStatusListener statusListener;  _ColorAnimationInfo(this.animation, this.colorTween, this.statusListener);}class ColorChangingNavigationBarState    extends State<ColorChangingNavigationBar> {  @override  void initState() {    _toColor = widget.startColor;    super.initState();  }  Color _toColor;  _ColorAnimationInfo _colorAnimationInfo;  void setAnimating(Animation animation, Color to) {    var fromColor;    if (_colorAnimationInfo != null) {      fromColor = _colorAnimationInfo.colorTween          .lerp(_colorAnimationInfo.animation.value);      _colorAnimationInfo.animation          .removeStatusListener(_colorAnimationInfo.statusListener);    } else {      fromColor = _toColor;    }    var statusListener = (state) {      if (state == AnimationStatus.completed ||          state == AnimationStatus.dismissed) {        setState(() {          _colorAnimationInfo = null;        });      }    };    animation.addStatusListener(statusListener);    setState(() {      _toColor = to;      Tween<Color> colorTween = new ColorTween(begin: fromColor, end: to);      _colorAnimationInfo =          new _ColorAnimationInfo(animation, colorTween, statusListener);    });  }  @override  Widget build(BuildContext context) {    if (_colorAnimationInfo != null) {      return new AnimatedBuilder(          animation: _colorAnimationInfo.animation,          builder: (context, child) { return new Container(   color: _colorAnimationInfo.colorTween       .lerp(_colorAnimationInfo.animation.value),   height: 30.0, );          });    } else {      return new Container(        color: _toColor,        height: 30.0,      );    }  }  @override  void dispose() {    if (_colorAnimationInfo != null) {      _colorAnimationInfo.animation.removeStatusListener(_colorAnimationInfo.statusListener);    }    _colorAnimationInfo = null;    super.dispose();  }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/437297.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号