Hero Animation Not Working in Flutter
Checked your code so the hero animation is working but its happening to fast because of the transition duration is only 300 milliseconds.
To achieve the below result you can make a 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())); }
You can use Custom MaterialPageRoute for the splash screen and for other routes MaterialPageRoute.
Hope it helps
// main.dart classimport 'package:flutter/material.dart';import 'package:flutter/scheduler.dart' show timeDilation;import 'package:flutter_test7/photo_hero.dart';import 'package:flutter_test7/second_page.dart';class HeroAnimation extends StatelessWidget { Widget build(BuildContext context) { timeDilation = 2.5; // 1.0 means normal animation speed. return new Scaffold( appBar: new AppBar( title: const Text('Basic Hero Animation'), ), body: new Center( child: new PhotoHero( photo: 'images/flippers-alpha.png', width: 300.0, onTap: () { Navigator.of(context).pushNamed('/second_page'); }, ), ), ); }}void main() { runApp( new MaterialApp( home: new HeroAnimation(), routes: <String, WidgetBuilder>{ '/second_page': (context) => new SecondPage() }, ), );}// photo_hero.dart classimport 'package:flutter/material.dart';class PhotoHero extends StatelessWidget { const PhotoHero({Key key, this.photo, this.onTap, this.width}) : super(key: key); final String photo; final VoidCallback onTap; final double width; Widget build(BuildContext context) { return new SizedBox( width: width, child: new Hero( tag: photo, child: new Material( color: Colors.transparent, child: new InkWell( onTap: onTap, child: new Image.asset( photo, fit: BoxFit.contain, ), ), ), ), ); }}// second_page.dart classimport 'package:flutter/material.dart';import 'package:flutter_test7/photo_hero.dart';class SecondPage extends StatefulWidget { @override _SecondPageState createState() => new _SecondPageState();}class _SecondPageState extends State<SecondPage> { @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: const Text('Flippers Page'), ), body: new Container( color: Colors.lightBlueAccent, padding: const EdgeInsets.all(16.0), alignment: Alignment.topLeft, child: new PhotoHero( photo: 'images/flippers-alpha.png', width: 100.0, onTap: () { Navigator.of(context).pop(); }, ), ), ); }}
Hope this helps.
Hero animation is quite easy to implement in Flutter. You just need to import the package package:flutter/scheduler.dart in your landing page. See below code
import 'package:flutter/scheduler.dart' show timeDilation;
Remember to add timeDilation variable and assign it a value to speed up or slow down the animation in seconds. Add these just after your build method as in example below
Widget build(BuildContext context) { timeDilation = 2;
For better animation, just use a custom animation