28

我按照Flutter 网站的说明制作了简单的英雄动画

它按照说明中的说明工作,但就我而言,我希望它从第一个屏幕到第二个屏幕的动画速度要慢得多。有谁知道如何改变这个动画的速度?

4

2 回答 2

41

要修改转换速度,您必须调整PageRoute转换持续时间(正如@diegoveloper 已经指出的那样)。

如果你想保持默认的过渡,你可以创建一个实现MaterialPageRoute的类。如果您已经拥有自己的过渡或想要创建一个过渡,则可以使用PageRouteBuilder轻松构建自己的过渡。只需调整transitionDuration.

这是一个小的独立示例,使用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,
          ),
        ),
      ),
    );
  }
}
于 2019-03-21T08:47:35.683 回答
4

1. 一个可能的解决方案

我不认为实现这一目标的唯一方法是改变PageRoute过渡持续时间。我认为您也可以通过使用 an 来达到相同的效果AnimationController——这个答案主要来自于Angela Yu 的 The Complete 2019 Flutter Development Bootcamp with Dart 的第 149 和第 150 讲课。

  1. 把你的屏幕变成StatefulWidget.
  2. 如果您只使用一个动画,请添加with SingleTickerProviderStateMixin到您的状态类。
  3. 在状态类中创建一个控制器。
  4. 如果您的动画应该出现在屏幕的初始化上,请使用controllerinsideinitState方法。
    • 控制器有一个名为 的属性duration,因此您可以根据自己的喜好对其进行更改。

2. 会是什么样子

最后,一切都应该看起来像这样:

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是一个必需的 ( @required) 参数,它采用状态(实例)对象本身(通常)。
  • addListenersetState如果您希望在将来的某个时间使用controller( ) 的值,是否存在controller.value- 例如,用类似的东西更改图标的高度height: finalHeight * controller.value
  • 为了过渡到这个屏幕,我只是使用FlatButtonwith Navigator.pushNamed,没什么特别的。

3. 一些额外的重要信息

  1. 即使您稍后更改屏幕,它controller仍将处于活动状态。所以如果你在后台有一个循环动画,最好在换屏的时候处理掉它,这样你就不会再浪费手机资源了。这可以通过以下方式实现:
    @override
    void dispose() {
      controller.dispose();
      super.dispose();
    }
    
  2. 您还可以自定义动画的运行方式或执行方式一种选择是使用CurvedAnimation.
    1. Animation animation;您的controller.
    2. controller在您的, inside下方initState,添加:
      animation = CurvedAnimation( // the controller can't have upperBound > 1
        parent: controller,        // the controller you created
        curve: Curves.decelerate,
      );
      
  3. 另一种有用的动画方法Flutter是使用TweenAnimations。例如,如果你想在颜色之间ColorTween转换,你可以使用(在你的下面controller,里面initState):
    animation = ColorTween(
      begin: Colors.red,
      end: Colors.blue,
    ).animate(controller);
    
于 2019-11-06T19:10:33.870 回答