问题
I have made simple hero animation following instructions from Flutter's website
It works as described in the instructions but in my case, I would like it to animate much more slowly from the first to the second screen. do anyone know how to change the speed of this animation?
回答1:
To modify the transition speed, you'll have to adjust the PageRoute transition duration (as already pointed out by @diegoveloper).
If you wanna keep the default transition, you can create a class implementing MaterialPageRoute. If you already have your own transition or want to create one you can use the PageRouteBuilder to easily build your own. Simply adjust the transitionDuration
.
Here's a small standalone example, using the PageRouteBuilder
:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Page1(),
);
}
}
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
RaisedButton(
child: Text('Page2'),
onPressed: () => Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(seconds: 2),
pageBuilder: (_, __, ___) => Page2())),
),
Hero(tag: 'home', child: Icon(Icons.home))
],
),
),
);
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Hero(
tag: 'home',
child: Icon(
Icons.home,
),
),
),
);
}
}
回答2:
1. A Possible Solution
I don't think the only way of achieving this is through changing the PageRoute
transition duration. I think you could also achieve the same effect by using an AnimationController
— this answer comes largely from lectures #149 and #150 of Angela Yu's The Complete 2019 Flutter Development Bootcamp with Dart.
- Turn your screen into a
StatefulWidget
. - If you're using only one animation, add
with SingleTickerProviderStateMixin
to your state class. - Create a controller inside the state class.
- If your animation is supposed to appear on the initialization of the screen, use the
controller
inside theinitState
method.- The controller has a property called
duration
, so you can change it to your liking.
- The controller has a property called
2. How It Would Look Like
In the end, everything should look a bit like this:
class _NewScreenState extends State<HomeScreen>
with SingleTickerProviderStateMixin{
AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this,
);
controller.forward();
controller.addListener((){
setState(() {
});
});
}
@override
Widget build(BuildContext context) {
return ...
vsync
is a required (@required
) parameter that takes the state (instance) object itself (usually).addListener
andsetState
are there if you wish to use the value of thecontroller
(controller.value
) at some point in the future — for example, changing the height of the icon with something likeheight: finalHeight * controller.value
.- For the transition into this screen, I'm simply using a
FlatButton
withNavigator.pushNamed
, nothing special.
3. Some Additional Important Info
- The
controller
will still be active even if you change screens later. So if you have a looping animation in the background, it's a good idea to dispose it when changing the screen, this way you don't waste phone resources with it anymore. This could be achieved with:@override void dispose() { controller.dispose(); super.dispose(); }
- You could also customize how the animation is run, or how it is executed. One option is to use a
CurvedAnimation
.- Declare
Animation animation;
right below yourcontroller
. - Below your
controller
, insideinitState
, add:animation = CurvedAnimation( // the controller can't have upperBound > 1 parent: controller, // the controller you created curve: Curves.decelerate, );
- Declare
- Another useful way of animating in
Flutter
is by using TweenAnimations. For example, if you want to transition between colors, you could useColorTween
(below yourcontroller
, insideinitState
):animation = ColorTween( begin: Colors.red, end: Colors.blue, ).animate(controller);
来源:https://stackoverflow.com/questions/53727361/how-to-change-speed-of-a-hero-animation-in-flutter