【问题标题】:How to create a Slide-In and Slide-Out animation in Flutter?如何在 Flutter 中创建滑入滑出动画?
【发布时间】:2020-05-16 22:38:53
【问题描述】:

我正在尝试在 Flutter 中创建滑入和滑出动画。动画应该是这样的:

----- Widget slides in ---> Wait for 1 seconds -----Widget slides out of screen -->

我尝试了以下代码,但我的动画卡在了一个循环中。

class _MyStatefulWidgetState extends State<MyStatefulWidget> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Offset> _positionAnimation;
  Animation<double> opacityAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );

    _positionAnimation = Tween<Offset>(
      begin: const Offset(-1, 0),
      end: const Offset(0, 0.0),
    ).animate(
      CurvedAnimation(
          parent: _controller,
          curve: Curves.elasticOut),
    )..addStatusListener((status) {
        print('animation 1 status $status');
        if (status == AnimationStatus.completed) {
          _controller.reset();
        }
        if (status == AnimationStatus.dismissed) {
          _positionAnimation = Tween<Offset>(
            begin: const Offset(0, 0),
            end: const Offset(1, 0.0),
          ).animate(
            CurvedAnimation(
                parent: _controller,
                curve: Curves.elasticIn),
          )..addStatusListener((status2) {
              print('animation 2 status $status2');
            if (status == AnimationStatus.dismissed) {
              _controller.reset();
            }
            });
          _controller.forward();
        }
      });
    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      builder: _buildAnimation,
      animation: _controller,
    );
  }

  Widget _buildAnimation(BuildContext context, Widget child) {
    return Opacity(
      opacity: 1,
      child: SlideTransition(
        position: _positionAnimation,
        child: Container(
          color: Colors.blueAccent,
          height: 100,
          child: Center(
            child: Text(
              'Hello, World!',
              style: Theme.of(context).textTheme.display1,
            ),
          ),
        ),
      ),
    );
  }

使用这种方法,动画会卡在一个循环中。

我无法使用交错动画,因为我正在尝试为相同的属性设置动画。 (或者有没有办法在同一属性上使用交错动画?)。 有更好的方法来实现吗?

【问题讨论】:

  • 如果使用 SlideTransition,则不需要 AnimatedBuilder
  • @pskink 我也尝试过使用 SlideTransition 但无法实现所需的行为。
  • child: TweenAnimationBuilder( onEnd: () { print('onEnd'); Future.delayed(Duration(milliseconds: 1000), () =&gt; setState(() =&gt; xpos = xpos == 0? 1 : 0)); }, duration: Duration(milliseconds: 750), tween: Tween&lt;Offset&gt;(begin: Offset(1, 0), end: Offset(xpos, 0)), builder: (context, offset, child) { return FractionalTranslation( translation: offset, child: Container(width: double.infinity, child: Text('animated text', textScaleFactor: 3.0,)), ); }, ), - 这里xpos是一个双字段,初始值为0.0
  • @pskink 这几乎可以工作。我在您的代码中几乎没有修改就达到了预期的效果。将其发布为答案。谢谢

标签: animation flutter dart flutter-animation


【解决方案1】:

从 cmets 中的@pskink 代码中汲取灵感,使用TweenAnimationBuilder 使用以下代码达到预期效果:

class _SlideInOutWidgetState extends State<SlideInOutWidget>
    with SingleTickerProviderStateMixin {
  double startPos = -1.0;
  double endPos = 0.0;
  Curve curve = Curves.elasticOut;
  @override
  Widget build(BuildContext context) {
    return TweenAnimationBuilder(
      tween: Tween<Offset>(begin: Offset(startPos, 0), end: Offset(endPos, 0)),
      duration: Duration(seconds: 1),
      curve: curve,
      builder: (context, offset, child) {
        return FractionalTranslation(
          translation: offset,
          child: Container(
            width: double.infinity,
            child: Center(
              child: child,
            ),
          ),
        );
      },
      child: Text('animated text', textScaleFactor: 3.0,),
      onEnd: () {
        print('onEnd');
        Future.delayed(
          Duration(milliseconds: 500),
          () {
            curve = curve == Curves.elasticOut
                ? Curves.elasticIn
                : Curves.elasticOut;
            if (startPos == -1) {
              setState(() {
                startPos = 0.0;
                endPos = 1.0;
              });
            }
          },
        );
      },
    );
  }
}

【讨论】:

    【解决方案2】:

    使用Marquee 插件进行文本动画

    安装:

      marquee: ^1.3.1
    

    例子:

    Marquee(
      text: 'There once was a boy who told this story about a boy: "',
    )
    

    更多信息请尝试marquee | flutterpckage

    【讨论】:

    • 我试过这个,但它没有给我想要的效果。使用这个库,文本会不断滚动。我希望文本从左侧滑入(使用 easeOut 曲线)停留 1 秒,然后从屏幕右侧滑出(使用 easeIn 曲线)
    猜你喜欢
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    相关资源
    最近更新 更多