Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change speed of a hero animation in flutter

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?

like image 564
Asger Lorenzen Avatar asked Dec 11 '18 15:12

Asger Lorenzen


People also ask

How do you animate in Flutter on hero?

The hero refers to the widget that flies between screens. Create a hero animation using Flutter's Hero widget. Fly the hero from one screen to another. Animate the transformation of a hero's shape from circular to rectangular while flying it from one screen to another.

What is vsync in animation Flutter?

What is vsync ? Vsync basically keeps the track of screen, so that Flutter does not renders the animation when the screen is not being displayed.


2 Answers

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:

Transition Demo

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,           ),         ),       ),     );   } } 
like image 64
NiklasPor Avatar answered Oct 26 '22 09:10

NiklasPor


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.

  1. Turn your screen into a StatefulWidget.
  2. If you're using only one animation, add with SingleTickerProviderStateMixin to your state class.
  3. Create a controller inside the state class.
  4. If your animation is supposed to appear on the initialization of the screen, use the controller inside the initState method.
    • The controller has a property called duration, so you can change it to your liking.

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 and setState are there if you wish to use the value of the controller (controller.value) at some point in the future — for example, changing the height of the icon with something like height: finalHeight * controller.value.
  • For the transition into this screen, I'm simply using a FlatButton with Navigator.pushNamed, nothing special.

3. Some Additional Important Info

  1. 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(); } 
  2. You could also customize how the animation is run, or how it is executed. One option is to use a CurvedAnimation.
    1. Declare Animation animation; right below your controller.
    2. Below your controller, inside initState, add:
      animation = CurvedAnimation( // the controller can't have upperBound > 1   parent: controller,        // the controller you created   curve: Curves.decelerate, ); 
  3. Another useful way of animating in Flutter is by using TweenAnimations. For example, if you want to transition between colors, you could use ColorTween (below your controller, inside initState):
    animation = ColorTween(   begin: Colors.red,   end: Colors.blue, ).animate(controller); 
like image 42
Philippe Fanaro Avatar answered Oct 26 '22 08:10

Philippe Fanaro