【问题标题】:Flutter Float and Fade In Animation for Widgets in Column with Loading for the First TimeFlutter Float 和 Fade In Animation for Columns 中第一次加载的小部件
【发布时间】:2021-07-30 11:58:06
【问题描述】:

我正在尝试创建动画屏幕,例如,当屏幕加载时,每个屏幕都将包含一个带有小部件的列。我想做的是,当屏幕加载时,让列中的每个小部件按照它们出现的顺序从屏幕外(从底部)浮动。

我一直在寻找,但似乎找不到解决方案。我怎样才能做到这一点?

【问题讨论】:

  • 请添加您的代码。

标签: flutter animation widget


【解决方案1】:

我做了一些可能是你想要的。但是,为了使每个元素在最后一个元素之后为自己而不是全部动画,我必须使用ListView.builder 来获取index。如果您能找到元素的index,则可以使用Column 小部件。

代码如下:

主屏幕:

import 'package:flutter/material.dart';
import 'package:testing/fade_in_from_bottom.dart';

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  final List<Widget> children = <Widget>[
    Container(
      height: 32.0,
      color: Colors.amber,
    ),
    Container(
      height: 32.0,
      color: Colors.black,
    ),
    Container(
      height: 32.0,
      color: Colors.purple,
    ),
    Container(
      height: 32.0,
      color: Colors.green,
    ),
    Container(
      height: 32.0,
      color: Colors.indigo,
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              itemCount: children.length,
              itemBuilder: (BuildContext context, int index) {
                return FadeInFromBottom(
                  key: UniqueKey(), // this is very important
                  index: index,
                  child: children[index],
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

这是我制作的FadeInFromBottom 小部件:

import 'package:flutter/material.dart';

class FadeInFromBottom extends StatefulWidget {
  @override
  _FadeInFromBottomState createState() => _FadeInFromBottomState();
  final Key key;
  final Duration animationDuration;
  final Duration offsetDuration;
  final Widget child;
  final int index;
  FadeInFromBottom({
    @required this.key,
    @required this.child,
    @required this.index,
    this.animationDuration = const Duration(milliseconds: 400),
    this.offsetDuration = const Duration(milliseconds: 800),
  }) : super(key: key); // this line is important
}

// How to add AutomaticKeepAliveClientMixin? Follow steps 1, 2 and 3:

// 1. add AutomaticKeepAliveClientMixin to FadeInFromBottom widget State
class _FadeInFromBottomState extends State<FadeInFromBottom>
    with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
  bool get wantKeepAlive => true; // 2. add this line
  double progress = 0.0;

  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    final Duration offsetDuration =
        widget.offsetDuration == null ? 0.0 : widget.offsetDuration;
    final int index = widget.index == null ? 0 : widget.index;
    
    // we await the future to create the animation delay
    Future.delayed(offsetDuration * index).then(
      (_) {
        controller = AnimationController(
            duration: widget.animationDuration, vsync: this);
        animation = Tween<double>(begin: 0.0, end: 1.0).animate(
          CurvedAnimation(
            parent: controller,
            curve: Curves.linear,
          ),
        )..addListener(() {
            setState(() => progress = animation.value);
          });

        controller.forward();
      },
    );
  }

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

  @override
  Widget build(BuildContext context) {
    super.build(context); // 3. add this line
    return Opacity(
      opacity: progress,
      child: Transform.translate(
        offset: Offset(
          0.0,
          (1.0 - progress) * 999.0,
        ),
        child: widget.child,
      ),
    );
  }
}

不要忘记添加key: UniqueKey() 属性,没有它动画会搞砸。

【讨论】:

  • 谢谢。这很好用。唯一的事情是当我更改 UI 时它会重播动画。就像在页面视图之间切换(它在其中一个页面中)。
  • 我很高兴它对你有用。要在每次从一页切换到另一页时停止动画,您可以将 AutomaticKeepAliveClientMixin 添加到 FadeInFromBottom 小部件。我在FadeInFromBottom 小部件的状态中添加了 3 行代码。第一个是为FadeInFromBottom 的状态类声明的地方。第二个在类内部(添加getter wantKeepAlive),第三个在build 方法中(调用super.build(context))。请检查一下,让我知道它是否适合您。
猜你喜欢
  • 2018-09-19
  • 1970-01-01
  • 2020-05-13
  • 2018-07-11
  • 1970-01-01
  • 2020-08-22
  • 2022-12-18
  • 2015-04-16
  • 2016-09-10
相关资源
最近更新 更多