【问题标题】:Problems with multiple tween animations in Flutter - Videos IncludedFlutter 中多个补间动画的问题 - 包含视频
【发布时间】:2019-04-21 05:37:21
【问题描述】:

我正在尝试创建的某个动画有一个奇怪的颤振问题。

我正在尝试将图像动画到屏幕上。 我希望它在 x 轴上移动,我也希望它慢慢淡入。

所以我想到了 - Positioned 和 Opacity,并使用补间动画来设置它们的值。

Positioned 和 Opacity 小部件单独工作时效果很好,但是当我将两者结合时 - 我得到一个奇怪的动画,它只是在一段时间后(大约 3 秒)才开始绘制。

我尝试打印animation.value,它似乎很好,从0.0 慢慢爬升到1.0 - 但云突然出现在大约 3 秒后。

我尝试将它们分离到不同的控制器,我认为这可能是罪魁祸首,但不是。

TLDR 视频:

Opacity Animation Only

Positioned Animation Only

Both Animations Combined - NOT GOOD

这是小部件的代码:

import 'package:app/weather/widgets/CloudProperties.dart';
import 'package:flutter/widgets.dart';

class WeatherCloudWidget extends StatefulWidget {
  final double sunSize;
  final CloudProperties properties;

  WeatherCloudWidget({Key key, this.properties, this.sunSize})
      : super(key: key);

  @override
  State<StatefulWidget> createState() => _WeatherCloudWidget();
}

class _WeatherCloudWidget extends State<WeatherCloudWidget>
    with TickerProviderStateMixin {
  AnimationController controller;
  AnimationController controller2;

  Animation<double> position;
  Animation<double> opacity;

  @override
  initState() {
    super.initState();
    _startAnimation();
  }

  @override
  Widget build(BuildContext context) {
    // screen width and height
    final screenWidth = MediaQuery.of(context).size.width;
    final screenHeight = MediaQuery.of(context).size.height;

    final properties = widget.properties;

    var vertical =
        screenHeight * 0.5 + (widget.sunSize * properties.verticalOffset * -1);

    var horizontal = (screenWidth * 0.5) + (widget.sunSize * position.value);

    print(opacity.value);

    // both Positioned & Opacity widgets

    return Positioned(
        left: horizontal,
        top: vertical,
        child: Opacity(
          opacity: opacity.value,
          child: Image.asset(
            properties.path,
            width: properties.getScaledWidth(widget.sunSize),
            height: properties.getScaledHeight(widget.sunSize),
          ),
        ));

    // Positioned only

    return Positioned(
        left: horizontal,
        top: vertical,
        child: Image.asset(
          properties.path,
          width: properties.getScaledWidth(widget.sunSize),
          height: properties.getScaledHeight(widget.sunSize),
        ));

    // Opacity only

    return Positioned(
        left: (screenWidth * 0.5) + (widget.sunSize * properties.tween[1]),
        top: vertical,
        child: Opacity(
          opacity: opacity.value,
          child: Image.asset(
            properties.path,
            width: properties.getScaledWidth(widget.sunSize),
            height: properties.getScaledHeight(widget.sunSize),
          ),
        ));
  }

  @override
  dispose() {
    controller.dispose();
    controller2.dispose();
    super.dispose();
  }

  void _startAnimation() {
    controller = AnimationController(
        duration: const Duration(milliseconds: 5000), vsync: this);

    controller2 = AnimationController(
        duration: const Duration(milliseconds: 5000), vsync: this);

    position = Tween(
            begin: widget.properties.tween[0], end: widget.properties.tween[1])
        .animate(
            new CurvedAnimation(parent: controller, curve: Curves.decelerate))
          ..addListener(() => setState(() {}));

    opacity = Tween(begin: 0.0, end: 1.0).animate(controller2)
      ..addListener(() => setState(() {}));

    controller.forward();
    controller2.forward();
  }
}

【问题讨论】:

    标签: dart flutter flutter-layout flutter-animation


    【解决方案1】:

    好的,伙计们。我设法使用SlideTransition 和FadeTransition 对此进行了排序。 我想我们应该只将Transition 小部件用于...过渡?而像Positioned 和Opacity 这样的东西是针对更多静态小部件的?不确定...

    它的样子:https://youtu.be/hj7PkjXrgfg

    无论如何,这里是替换代码,如果有人在寻找参考:

    class WeatherCloudWidget extends StatefulWidget {
      final double sunSize;
      final CloudProperties properties;
    
      WeatherCloudWidget({Key key, this.properties, this.sunSize})
          : super(key: key);
    
      @override
      State<StatefulWidget> createState() => _WeatherCloudWidget();
    }
    
    class _WeatherCloudWidget extends State<WeatherCloudWidget>
        with TickerProviderStateMixin {
      AnimationController controller;
      Animation<Offset> position;
      Animation<double> opacity;
    
      final alphaTween = new Tween(begin: 0.0, end: 1.0);
    
      @override
      initState() {
        super.initState();
        _startAnimation();
      }
    
      @override
      Widget build(BuildContext context) {
        // screen width and height
        final screenWidth = MediaQuery.of(context).size.width;
        final screenHeight = MediaQuery.of(context).size.height;
    
        final properties = widget.properties;
    
        var vertical = (screenHeight * 0.5) +
            (widget.sunSize * properties.verticalOffset * -1);
    
        var horizontal =
            (screenWidth * 0.5) + (widget.sunSize * properties.tweenEnd);
    
        return Positioned(
          left: horizontal,
          top: vertical,
          child: SlideTransition(
              position: position,
              child: FadeTransition(
                opacity: opacity,
                child: Image.asset(
                  properties.path,
                  width: properties.getScaledWidth(widget.sunSize),
                  height: properties.getScaledHeight(widget.sunSize),
                ),
              )),
        );
      }
    
      @override
      dispose() {
        controller.dispose();
        super.dispose();
      }
    
      void _startAnimation() {
        controller = AnimationController(
            duration: const Duration(milliseconds: 2000), vsync: this);
    
        position = new Tween<Offset>(
          begin: new Offset(widget.properties.tweenStart, 0.0),
          end: new Offset(0.0, 0.0),
        ).animate(new CurvedAnimation(parent: controller, curve: Curves.decelerate));
    
        opacity = alphaTween.animate(controller);
    
        controller.forward();
      }
    }
    

    【讨论】:

    • 监听器中不需要addListener 和setState(它会重建WeatherCloudWidget)-controller.forward(); 就足够了
    • 您介意制作新版本的视频吗? (我很好奇):)
    • 嘿@Feu,我已将视频添加到答案中。
    • @pskink - 你当然是对的!这是我在动画不起作用时尝试过的,忘记删除它。
    • 理论上你的WeatherCloudWidget现在可能是StatelessWidget?还是不行?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-26
    • 2023-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多