Flutter AnimatedList还是简陋? [英] Flutter AnimatedList still janky?

查看:34
本文介绍了Flutter AnimatedList还是简陋?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在Flutter应用中使用AnimatedList,但删除列表项的动画输出方式存在问题.
动画本身可以按预期工作,但是一旦删除的项目完成动画处理,它就会消失,从而导致其他小部件跳入其位置.我曾期望其他项目过渡到已删除项目的位置...

I'm currently using an AnimatedList in my Flutter app and having problems with the way removed list items are animated out.
The animation itself works as expected but once the removed item finishes animating, it just disappears causing the other widgets to jump into its place. I had expected the other items to transition into the place of the removed item ...

我尝试用 ScaleTransition 包装列表项,但这无济于事-其他列表项在完成动画之前仍然不会对已删除的项做出反应.

I tried wrapping my list items with a ScaleTransition but that didn't help - the other list items still do not react to the removed item until it has finished the animation.

这种违背AnimatedList的目的,对吗?还是我做错了什么?关于AnimatedList的一周小部件"视频清楚地表明,列表项通过更改位置来对新插入的项做出反应...

This kind of defies the purpose of AnimatedList, right? Or did I do something wrong? The "Widget of the week" video about AnimatedList clearly shows that list items react to newly inserted items by changing their position ...

这是我的代码:

@override
Widget build(BuildContext context) {
  return AnimatedList(
    padding: EdgeInsets.only(top: REGULAR_DIM,
        bottom: REGULAR_DIM + kBottomNavigationBarHeight),
    initialItemCount: data.length,
    itemBuilder: (context, index, animation) {
      return MyCustomWidget(
          data: data[index],
          animation: animation,
          disabled: false
      );
    },
  );
}

class MyCustomWidget extends AnimatedWidget {
  final MyModel data;
  final bool disabled;

  MyCustomWidget({
    @required this.data,
    @required Animation<double> animation,
    this.disabled = false
  }) : super(listenable: animation);

  Animation<double> get animation => listenable;


  @override
  Widget build(BuildContext context) {
    final content = ... ;

    return ScaleTransition(
      scale: CurvedAnimation(
          parent: animation,
          curve: Interval(0, 0.25)
      ).drive(Tween(begin: 0, end: 1)),
      child: FadeTransition(
        opacity: animation,
        child: SlideTransition(
          position: animation.drive(
              Tween(begin: Offset(-1, 0), end: Offset(0, 0))
                  .chain(CurveTween(curve: Curves.easeOutCubic))),
          child: content,
        ),
      ),
    );
  }
}

然后在MyCustomWidget中的某个地方调用此函数:

And then somewhere in the MyCustomWidget I invoke this function:

void _remove(BuildContext context) async {
        final animatedList = AnimatedList.of(context);

        // obtain myModel asynchronously

        myModel.removeData(data);
        animatedList.removeItem(index, (context, animation) => MyCustomWidget(
          data: data,
          animation: animation,
          disabled: true,
        ), duration: Duration(milliseconds: 350));
      }

推荐答案

关键是触发两个Transition(一个SlideTranstion()和另一个SizeTransition)以消除在删除该项目时跳转的情况

The key is to trigger two Transitions one SlideTranstion() and another SizeTransition to eliminate to jump when the item is removed

这是一些示例代码

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: Text('Update AnimatedList data')),
        body: BodyWidget(),
      ),
    );
  }
}

class BodyWidget extends StatefulWidget {
  @override
  BodyWidgetState createState() {
    return new BodyWidgetState();
  }
}

class BodyWidgetState extends State<BodyWidget>
    with SingleTickerProviderStateMixin {
  // the GlobalKey is needed to animate the list
  final GlobalKey<AnimatedListState> _listKey = GlobalKey(); // backing data
  List<String> _data = ['Horse', 'Cow', 'Camel', 'Sheep', 'Goat'];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SizedBox(
          height: 400,
          child: AnimatedList(
            key: _listKey,
            initialItemCount: _data.length,
            itemBuilder: (context, index, animation) {
              return _buildItem(
                _data[index],
                animation,
              );
            },
          ),
        ),
        RaisedButton(
          child: Text(
            'Insert single item',
            style: TextStyle(fontSize: 20),
          ),
          onPressed: () {
            _onButtonPress();
          },
        ),
        RaisedButton(
          child: Text(
            'Remove single item',
            style: TextStyle(fontSize: 20),
          ),
          onPressed: () {
            _removeSingleItems();
          },
        ),
      ],
    );
  }

  Widget _buildItem(String item, Animation<double> animation, {direction: 0}) {
    return (direction == 0)
        ? SizeTransition(
            sizeFactor: animation,
            child: Card(
              color: Colors.amber,
              child: ListTile(
                title: Text(
                  item,
                  style: TextStyle(fontSize: 20),
                ),
              ),
            ),
          )
        : Stack(
            children: [
              SizeTransition(
                sizeFactor: animation,
                child: Card(
                  color: Colors.transparent,
                  child: ListTile(
                    title: Text(
                      item,
                      style: TextStyle(fontSize: 20),
                    ),
                  ),
                ),
              ),
              Align(
                alignment: Alignment.topCenter,
                heightFactor: 0,
                child: SlideTransition(
                  position: animation
                      .drive(Tween(begin: Offset(-1, 0), end: Offset(0, 0))),
                  child: Card(
                    color: Colors.red,
                    child: ListTile(
                      title: Text(
                        item,
                        style: TextStyle(fontSize: 20),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          );
  }

  void _onButtonPress() {
    _insertSingleItem();
  }

  void _insertSingleItem() {
    String item = "Pig";
    int insertIndex = 2;
    _data.insert(insertIndex, item);
    _listKey.currentState.insertItem(insertIndex);
  }

  void _removeSingleItems() {
    int removeIndex = 2;
    String removedItem = _data.removeAt(removeIndex);
    // This builder is just so that the animation has something
    // to work with before it disappears from view since the
    // original has already been deleted.
    AnimatedListRemovedItemBuilder builder = (context, animation) {
      // A method to build the Card widget.

      return _buildItem(removedItem, animation, direction: 1);
    };
    _listKey.currentState.removeItem(removeIndex, builder);
  }

  void _updateSingleItem() {
    final newValue = 'I like sheep';
    final index = 3;
    setState(() {
      _data[index] = newValue;
    });
  }
}
enter code here

这篇关于Flutter AnimatedList还是简陋?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆