Flutter FadeIn/FadeOut 动画一起

Flutter FadeIn/FadeOut animation together

在这个简单的示例代码中,我想同时使用 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. FadeTransition class 不应该采用 animation 不透明度,而应该是 _fadeInFadeOut 变量
  2. 动画开始,当你调用 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 中组合 FadeOut 并给 FadeOut 延迟量大于 [=12= 的持续时间],只需复制并粘贴,然后将 Image.asset 小部件更改为您想要淡入淡出的任何内容 in/out

          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

为此使用 AnimatedOpacity 小部件。

注意:为了可见性 on/off 做 opacitytruefalse。控制child淡入淡出过渡的动画。

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,
          ),
        ),
      ),
    );
  }
}