如何在 Flutter 中向 AnimationController 添加 Curves 类动画?

Posted

技术标签:

【中文标题】如何在 Flutter 中向 AnimationController 添加 Curves 类动画?【英文标题】:How do you add a Curves class animation to AnimationController in Flutter? 【发布时间】:2019-08-17 05:50:58 【问题描述】:

我正在尝试将曲线类动画“Curves.bounceOut”添加到使用 AnimationController 的代码中。

这是我的代码:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: MyHomePage(),
    );
  


class MyHomePage extends StatefulWidget 
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin 
  var squareScale = 1.0;
  static AnimationController _controller;

  @override
  void initState() 
    _controller = AnimationController(
        vsync: this,
        lowerBound: 0.5,
        upperBound: 1.0,
        duration: Duration(milliseconds: 300));

    _controller.addListener(() 
      setState(() 
        squareScale = _controller.value;
      );
    );

    super.initState();
  

  @override
  void dispose() 
    _controller.dispose();
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("Bounce Example"),
      ),
      body: Stack(
        children: <Widget>[
          Container(
            width: 150.0,
            height: 150.0,
            color: Colors.yellowAccent,
          ),
          Column(
            children: <Widget>[
              Row(
                children: <Widget>[
                  GestureDetector(
                    onTap: () 
                      _controller.forward(from: 0.0);
                    ,
                    child: Transform.scale(
                      scale: squareScale,
                      child: Container(
                        width: 150.0,
                        height: 150.0,
                        color: Colors.green,
                      ),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
    );
  

目前,绿色容器的动画从 0.5 缩放到 1.0 缩放,但不会反弹。如何添加“Curves.bounceOut”动画,以便容器在点击时弹跳?

提前感谢您的帮助!

【问题讨论】:

CurvedAnimation 我已经看到了 CurvedAnimation 类,但我不知道如何将它正确地包含在我的代码中。 而不是_controller.addListener 使用_curvedAnimation.addListener ? 【参考方案1】:

您需要同时使用动画控制器和补间,这将允许您添加Curves.bounceOut

在代码中的某处添加:

AnimationController _controller;
var scaleAnimation;

在你的initState() 方法中:

_controller = new AnimationController(
 duration: new Duration(milliseconds: 300),
 vsync: this
)
..addListener(() 
  setState(() );
);
scaleAnimation = new Tween(
  begin: 0.5,
  end: 1.0,
).animate(new CurvedAnimation(
  parent: _controller,
  curve: Curves.bounceOut
));

注意..addListener() 是一段不错的 dart 代码,可让您轻松添加侦听器。 Tween 基本上是在告诉您的动画,它需要在AnimationController 给定的时间范围内从begin 中的值变为end 中的值。要在您的代码中使用此值,您现在只需设置动画结果的比例:

child: Transform.scale(
  scale: scaleAnimation.value,
  child: Container(
    width: 150.0,
    height: 150.0,
    color: Colors.green,
  ),
),

当动画被调用时,它会自动更新容器的比例。

编辑:

将您的小部件更改为:

child: isChanging ? Transform.scale(
  scale: scaleAnimation.value,
  child: Container(
    width: 150.0,
    height: 150.0,
    color: Colors.green,
  ),
) : Transform.scale(
  scale: 1.0,
  child: Container(
    width: 150.0,
    height: 150.0,
    color: Colors.green,
  ),
),

beginend 参数分别保留为0.51.0,但在转发控制器之前在onTap() 方法中添加:

onTap: () 
  setState(() 
    isChanging = true
  );
  _controller.forward(from: 0.0);

在代码中的任何位置添加bool isChanging 行。最后,您需要在动画结束时重置显示的小部件,因此将 scaleAnimation 更改为:

child: Transform.scale(
  scale: scaleAnimation.value,
  child: Container(
    width: 150.0,
    height: 150.0,
    color: Colors.green,
  ),
)..addStatusListener((AnimationStatus status) 
  if (status == AnimationStatus.completed)  //the animation is finished
    _controller.reset();
    setState(() 
      isChanging = false;
    
  
);

【讨论】:

感谢这工作!你知道在触发任何动画之前如何让容器以 150.0 x 150.0 的宽度开始吗?现在它从 0.5 开始,而不是 1.0。 您可以在scaleAnimation 中交换beginend 参数。这将使规模从1.0 开始并变得越来越小。希望这会有所帮助! 抱歉,我可能不够清楚。每次点击容器时,我希望动画从 0.5 变为 1.0。但是,当应用程序首次启动时,容器以 0.5 的比例开始,我希望它以 1.0 的比例开始,然后在点击时直接跳转到 0.5 并动画到 1.0。这可能吗?再次感谢您的帮助。 @hello_friend 有可能......你必须将beginend 参数both 设置为1.0,然后让你的曲线成为一部分sin(x) 曲线。然而,即便如此,动画也不会立即从 1.0 跳到 0.5。可能你可以在小部件所在的位置有一个条件语句,如果布尔值为真,那么它会显示容器的 1.0 比例,然后当你单击按钮时它会将其设置为假,将小部件更改为比例为 0.5 的小部件然后在该小部件上运行动画。如果您需要我将其添加到我的答案中,请告诉我。 如果您将此添加到您的答案中,那就太好了。【参考方案2】:

更简洁的方法是使用controller.drive()CurveTween

anim = animController.drive(CurveTween(curve: Curves.easeOut));

然后在您的小部件树中使用anim.value

如果你愿意,也可以内联:

Opacity(opacity: controller.drive(CurveTween(curve: Curves.easeOut)).value)

【讨论】:

以上是关于如何在 Flutter 中向 AnimationController 添加 Curves 类动画?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 的 Firestore 中向数组中添加相等的元素?

在 Flutter 中向云函数传递参数

在 Flutter 中向 CarouselSlider Widget 显示 JSON 数据

在 setState() 方法中向 List 添加元素,而不是保存元素 Flutter

如何在颤振中向 multiDexKeepFile 添加类?

想要向新用户显示欢迎页面,并在 Flutter Firebase 中向登录用户显示主屏幕