Flutter FadeIn/FadeOut 动画一起

Posted

技术标签:

【中文标题】Flutter FadeIn/FadeOut 动画一起【英文标题】:Flutter FadeIn/FadeOut animation together 【发布时间】:2019-12-23 18:50:27 【问题描述】:

在这个简单的示例代码中,我想同时使用fadeIn 和fadeOut 动画,但是在此代码中,fadeIn 只能工作而reverse 不能工作,我怎样才能将它们都放在一起?

import 'package:flutter/material.dart';

void main()=>runApp(MaterialApp(home: FadeTransitionSample(),));
class FadeTransitionSample extends StatefulWidget 
  @override
  State<StatefulWidget> createState() => _Fade();


class _Fade extends State<FadeTransitionSample> with TickerProviderStateMixin 
  AnimationController animation;
  Animation<double> _fadeInFadeOut;

  @override
  void initState() 
    super.initState();
    animation = AnimationController(vsync: this, duration: Duration(seconds: 3),);
    _fadeInFadeOut = Tween<double>(begin: 0.0, end: 0.1).animate(animation);

    animation.addListener(()
      if(animation.isCompleted)
        animation.reverse();
      else
        animation.forward();
      
    );
    animation.repeat();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Container(
        child: Center(
          child: FadeTransition(
            opacity: animation,
            child: Container(
              color: Colors.green,
              width: 100,
              height: 100,
            ),
          ),
        ),
      ),
    );
  

【问题讨论】:

【参考方案1】:

好的,我假设您希望在容器上获得 FadeIn 和 FadeOut 动画。

您需要更改一些内容。

    FadeTransition 类不应将 animation 用于不透明度,而应使用 _fadeInFadeOut 变量 当您调用 animation.forward() 而不是 animation.repeat() 时,动画开始(因为在您的情况下,您还需要反转动画,请始终从 animation.forward() 调用开始)。

确保使用addStatusListener() 方法而不是addListener(),因为您可以更好地控制您的状态。

所以,所有这些放在一起,下面是使您的动画工作的工作代码。

import 'package:flutter/material.dart';

void main()=>runApp(MaterialApp(home: FadeTransitionSample(),));
class FadeTransitionSample extends StatefulWidget 
  @override
  State<StatefulWidget> createState() => _Fade();


class _Fade extends State<FadeTransitionSample> with TickerProviderStateMixin 
  AnimationController animation;
  Animation<double> _fadeInFadeOut;

  @override
  void initState() 
    super.initState();
    animation = AnimationController(vsync: this, duration: Duration(seconds: 3),);
    _fadeInFadeOut = Tween<double>(begin: 0.0, end: 0.5).animate(animation);

    animation.addStatusListener((status)
      if(status == AnimationStatus.completed)
        animation.reverse();
      
      else if(status == AnimationStatus.dismissed)
        animation.forward();
      
    );
    animation.forward();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Container(
        child: Center(
          child: FadeTransition(
            opacity: _fadeInFadeOut,
            child: Container(
              color: Colors.green,
              width: 100,
              height: 100,
            ),
          ),
        ),
      ),
    );
  

【讨论】:

谢谢。如何设置正向和反向之间的延迟? 目前,FadeIn 和 Fade Out 的延迟是相同的。如果您想为两个动作设置不同的持续时间,您必须创建单独的动画并使用它们。不能用简单的反向方法做到这一点。还有其他调用,如 animateTo() 和 animateBack() 您可以利用它们。【参考方案2】:

为此,请使用 AnimatedOpacity 小部件。

注意:要打开/关闭可见性,opacitytruefalse。控制孩子淡入淡出过渡的动画。

AnimatedOpacity 小部件需要三个参数:

opacity:从 0.0(不可见)到 1.0(完全可见)的值。 duration: 动画需要多长时间才能完成。 child:动画小部件。在这种情况下,绿色框。

这是代码文件:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget 
  const MyApp(Key? key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    const appTitle = 'Opacity Demo';
    return const MaterialApp(
      title: appTitle,
      home: MyHomePage(title: appTitle),
    );
  


// The StatefulWidget's job is to take data and create a State class.
// In this case, the widget takes a title, and creates a _MyHomePageState.
class MyHomePage extends StatefulWidget 
  const MyHomePage(
    Key? key,
    required this.title,
  ) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


// The State class is responsible for two things: holding some data you can
// update and building the UI using that data.
class _MyHomePageState extends State<MyHomePage> 
  // Whether the green box should be visible
  bool _visible = true;

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: AnimatedOpacity(
          // If the widget is visible, animate to 0.0 (invisible).
          // If the widget is hidden, animate to 1.0 (fully visible).
          opacity: _visible ? 1.0 : 0.0,
          duration: const Duration(milliseconds: 500),
          // The green box must be a child of the AnimatedOpacity widget.
          child: Container(
            width: 200.0,
            height: 200.0,
            color: Colors.red,
          ),
        ),
      ),
    );
  

【讨论】:

【参考方案3】:

简单的解决方案,直接用更少的代码,想法是在FadeIn 中组合FadeOut 并给FadeOut 延迟量大于FadeIn 的持续时间,只需复制和粘贴然后只需更改Image.asset 小部件到您想要淡入/淡出的任何内容

          FadeIn(
            animate: true,
            duration: Duration(seconds: 2),

            child: FadeOut(
              animate: true,
              delay: Duration(seconds: 2),
              duration: Duration(seconds: 1),
              
              // Just change the Image.asset widget to anything you want to fade in/out:
              child: Image.asset(
                "assets/images/logo.png",
                height: 150,
                width: 150,
                fit: BoxFit.contain,
              ), //Image.asset
              
            ) // FadeOut
          ), // FadeIn

【讨论】:

以上是关于Flutter FadeIn/FadeOut 动画一起的主要内容,如果未能解决你的问题,请参考以下文章

transitionend事件 监听 fadeIn fadeOut 两个方法无效(动画结束时无法执行transitionend里面的代码)

jQuery - fadeIn()、fadeOut()、animate()、stop() 和闪烁

210 jQuery淡入淡出:fadeIn() fadeOut() fadeToggle() fadeTo()

jQuery fadeIn fadeOut 背景问题

jQuery效果-----fadeIn()fadeOut()fadeToggle()fadeTo()

css 滑块 - 通过css的fadein / fadeout