【问题标题】:Animate elements in ListView on initialization在初始化时为 ListView 中的元素设置动画
【发布时间】:2020-04-18 02:36:02
【问题描述】:

我想实现如下(动画风格无所谓,我正在寻找方法做到这一点)

但是,所有资源和问题仅说明如何创建 项目添加或删除动画。

我当前的代码(我使用 BLoC 模式)

class _MembersPageState extends State<MembersPage> {
  @override
  Widget build(BuildContext context) {
    return BlocProvider<MembersPageBloc>(
      create: (context) =>
          MembersPageBloc(userRepository: UserRepository.instance)..add(MembersPageShowed()),
      child: BlocBuilder<MembersPageBloc, MembersPageState>(
        builder: (context, state) {
          if (state is MembersPageSuccess) {
            return ListView.builder(
              itemCount: state.users.length,
              itemBuilder: (context, index) {
                User user = state.users[index];

                return ListTile(
                  isThreeLine: true,
                  leading: Icon(Icons.person, size: 36),
                  title: Text(user.name),
                  subtitle: Text(user.username),
                  onTap: () => null,
                );
              },
            );
          } else
            return Text("I don't care");
        },
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart flutter-animation bloc flutter-animatedlist


    【解决方案1】:

    AnimatedOpacityAnimatedPositioned 这样的动画小部件可以做到这一点。通过这种方式,您可以使用不同的动画小部件、曲线、开始和结束值来制作不同的动画。

    然而,Listview 中子部件的生命周期有点复杂。它们会根据滚动位置被销毁和重新创建。如果子窗口小部件有一个在初始化时开始的动画,那么只要孩子对 UI 可见,它就会重新动画。

    这是我的 hacky 解决方案。我使用了一个静态布尔值来指示它是第一次还是娱乐状态,并且简单地忽略了娱乐。你可以在 Dartpad 中快速尝试一下。

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: Colors.black54),
          debugShowCheckedModeBanner: false,
          home: Scaffold(
              body: ListView(
            children: List.generate(
                25, (i) => AnimatedListItem(i, key: ValueKey<int>(i))),
          )),
        );
      }
    }
    
    class AnimatedListItem extends StatefulWidget {
      final int index;
    
      AnimatedListItem(this.index, {Key key}) : super(key: key);
    
      @override
      _AnimatedListItemState createState() => _AnimatedListItemState();
    }
    
    class _AnimatedListItemState extends State<AnimatedListItem> {
      bool _animate = false;
    
      static bool _isStart = true;
    
      @override
      void initState() {
        super.initState();
        _isStart
            ? Future.delayed(Duration(milliseconds: widget.index * 100), () {
                setState(() {
                  _animate = true;
                  _isStart = false;
                });
              })
            : _animate = true;
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return AnimatedOpacity(
          duration: Duration(milliseconds: 1000),
          opacity: _animate ? 1 : 0,
          curve: Curves.easeInOutQuart,
          child: AnimatedPadding(
            duration: Duration(milliseconds: 1000),
            padding: _animate
                ? const EdgeInsets.all(4.0)
                : const EdgeInsets.only(top: 10),
            child: Container(
              constraints: BoxConstraints.expand(height: 100),
              child: Card(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    widget.index.toString(),
                    style: TextStyle(fontSize: 24),
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }
    

    【讨论】:

    • 是的,我知道,但我没有添加或删除项目。我已经从后端收到了一些物品。我要做的就是为这些创建“布局”动画。
    • 好吧,我不得不说,当有更多项目时,滚动会产生严重的问题。我会接受这个,但效果不好。
    • 我将更新我的答案,使其仅在开始时动画。您也可以自己添加该逻辑。抱歉回复晚了。
    • 如何用这种方法实现上面gif中的“从底部滑动”效果。谢谢。
    【解决方案2】:

    我在 dartpad 上创建了一个 gist,展示了如何为 ListView 添加初始动画

    关键是为每个列表项创建一个AnimationController,缓存,动画完成后清理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-28
      • 2017-09-03
      相关资源
      最近更新 更多