英雄动画在Flutter中不起作用
问题内容:
因此,我正试图为一家杂乱无章的餐厅制作送货上门的应用程序,而我的英雄动画似乎无法正常工作。首先,我创建了一个初始屏幕,其中显示徽标,然后导航到该徽标应该进行英雄转换的主页。初始屏幕和主页位于两个独立的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
。
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。
希望能帮助到你