因此,我正试图为一家杂乱无章的餐厅制作送货上门的应用程序,而我的英雄动画似乎无法正常工作。首先,我创建了一个初始屏幕,其中显示徽标,然后导航到该徽标应该进行英雄转换的主页。初始屏幕和主页位于两个独立的dart文件中。这是我的初始屏幕的代码:
import 'package:flutter/material.dart'; import 'home_page.dart'; import 'dart:async'; class Splash extends StatefulWidget { @override _SplashState createState() => new _SplashState(); } class _SplashState extends State<Splash> with SingleTickerProviderStateMixin { Animation<double> _mainLogoAnimation; AnimationController _mainLogoAnimationController; @override void initState() { super.initState(); goToHomePage(); _mainLogoAnimationController = new AnimationController(duration: new Duration(milliseconds: 2500) ,vsync: this); _mainLogoAnimation = new CurvedAnimation(parent: _mainLogoAnimationController, curve: Curves.easeIn); _mainLogoAnimation.addListener(() => (this.setState(() {}))); _mainLogoAnimationController.forward(); } Future goToHomePage() async { await new Future.delayed(const Duration(milliseconds: 4000)); Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new HomePage())); } @override Widget build(BuildContext context) { return new Material( color: Colors.black, child: new Center( child: new Opacity( opacity: 1.0 * _mainLogoAnimation.value, child: new Hero( tag: 'tbh_logo', child: new Image( image: new AssetImage('assets/images/tbh_main_logo.png'), width: 300.0 ) ) ) ) ); } }
And here’s the code for the home page:
import 'package:flutter/material.dart'; import '../ui/drawer.dart'; import 'splash.dart'; class HomePage extends StatefulWidget { @override _HomePageState createState() => new _HomePageState(); } class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text("The Barni House"), backgroundColor: Colors.black, ), drawer: new Drawer(child: MyDrawer()), body: new Center( child: Column( children: <Widget>[ new Container( child: new Hero( tag: 'tbh_logo', child: new Image( image: new AssetImage('assets/images/tbh_main_logo.png'), width: 300.0 ) ) ) ], ) ), ); } }
检查您的代码,使英雄动画正常工作,但是由于过渡持续时间仅为300毫秒,因此动画发生得很快。
要获得以下结果,您可以创建一个Custom MaterialPageRoute。
Custom MaterialPageRoute
Before
@override Duration get transitionDuration => const Duration(milliseconds: 300);
After
@override Duration get transitionDuration => const Duration(milliseconds: 1000);
Also, you can play with the CurvedAnimation
new CurvedAnimation( parent: routeAnimation, curve: Curves.elasticIn, )
CustomRoute.dart
import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; final Tween<Offset> _kBottomUpTween = new Tween<Offset>( begin: const Offset(0.0, 1.0), end: Offset.zero, ); // Offset from offscreen to the right to fully on screen. final Tween<Offset> _kRightMiddleTween = new Tween<Offset>( begin: const Offset(1.0, 0.0), end: Offset.zero, ); // Offset from offscreen below to fully on screen. class AppPageRoute extends MaterialPageRoute<String> { @override final bool maintainState; @override final WidgetBuilder builder; CupertinoPageRoute<String> _internalCupertinoPageRoute; AppPageRoute({ @required this.builder, RouteSettings settings: const RouteSettings(), this.maintainState: true, bool fullscreenDialog: false, }) : assert(builder != null), assert(settings != null), assert(maintainState != null), assert(fullscreenDialog != null), super( settings: settings, fullscreenDialog: fullscreenDialog, builder: builder, ) { assert(opaque); // PageRoute makes it return true. } @override Color get barrierColor => null; @override Duration get transitionDuration => const Duration(milliseconds: 1000); CupertinoPageRoute<String> get _cupertinoPageRoute { assert(_useCupertinoTransitions); _internalCupertinoPageRoute ??= new CupertinoPageRoute<String>( builder: builder, fullscreenDialog: fullscreenDialog, hostRoute: this, ); return _internalCupertinoPageRoute; } bool get _useCupertinoTransitions { return _internalCupertinoPageRoute?.popGestureInProgress == true || Theme.of(navigator.context).platform == TargetPlatform.iOS; } @override Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { final Widget result = builder(context); assert(() { if (result == null) { throw new FlutterError('The builder for route "${settings.name}" returned null.\n' 'Route builders must never return null.'); } return true; }()); return result; } @override Widget buildTransitions( BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) { if (_useCupertinoTransitions) { return _cupertinoPageRoute.buildTransitions(context, animation, secondaryAnimation, child); } return new _CustomPageTransition(routeAnimation: animation, child: child, fullscreenDialog: fullscreenDialog); } } class _CustomPageTransition extends StatelessWidget { final Animation<Offset> _positionAnimation; final Widget child; final bool fullscreenDialog; _CustomPageTransition({ Key key, @required Animation<double> routeAnimation, @required this.child, @required this.fullscreenDialog, }) : _positionAnimation = !fullscreenDialog ? _kRightMiddleTween.animate(new CurvedAnimation( parent: routeAnimation, curve: Curves.elasticIn, )) : _kBottomUpTween.animate(new CurvedAnimation( parent: routeAnimation, // The route's linear 0.0 - 1.0 animation. curve: Curves.elasticIn, )), super(key: key); @override Widget build(BuildContext context) { return new SlideTransition( position: _positionAnimation, child: child, ); } }
Push new Route
Future goToHomePage() async { await new Future.delayed(const Duration(milliseconds: 4000)); Navigator.of(context).push(new AppPageRoute(builder: (BuildContext context) => new HomePage())); }
您可以将“自定义MaterialPageRoute”用于初始屏幕和其他路线MaterialPageRoute。
希望能帮助到你