【问题标题】:How to update data in an AnimatedList in Flutter如何在 Flutter 中更新 AnimatedList 中的数据
【发布时间】:2019-06-19 22:42:30
【问题描述】:

如何在 Flutter 的 AnimatedList 中更新数据(添加、删除行)?我可以通过更新支持数据并调用setState 在 ListView 中完成此操作。例如,

setState(() {
  _data.insert(2, 'pig');
});

不过,在 AnimatedList 中似乎更复杂。

【问题讨论】:

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


    【解决方案1】:

    下面演示了更新 AnimatedList 的各种方法。该过程每次都包括两个主要步骤:

    1. 更新数据集
    2. 通知 AnimatedList 的全局键有关更改

    插入单个项目

    在索引2处添加“猪”。

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

    插入多个项目

    在索引 2 处插入三只动物。

    final items = ['Pig', 'Chichen', 'Dog'];
    int insertIndex = 2;
    _data.insertAll(insertIndex, items);
    // This is a bit of a hack because currentState doesn't have
    // an insertAll() method.
    for (int offset = 0; offset < items.length; offset++) {
      _listKey.currentState.insertItem(insertIndex + offset);
    }
    

    删除单个项目

    从列表中删除“猪”。

    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);
    };
    _listKey.currentState.removeItem(removeIndex, builder);
    

    删除多个项目

    从列表中删除“骆驼”和“绵羊”。

    int removeIndex = 2;
    int count = 2;
    for (int i = 0; i < count; i++) {
      String removedItem = _data.removeAt(removeIndex);
      AnimatedListRemovedItemBuilder builder = (context, animation) {
        return _buildItem(removedItem, animation);
      };
      _listKey.currentState.removeItem(removeIndex, builder);
    }
    

    补充代码

    main.dart

    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> {
    
      // 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();
              },
            )
          ],
        );
      }
    
      Widget _buildItem(String item, Animation animation) {
        return SizeTransition(
          sizeFactor: animation,
          child: Card(
            child: ListTile(
              title: Text(
                item,
                style: TextStyle(fontSize: 20),
              ),
            ),
          ),
        );
      }
    
      void _onButtonPress() {
        // replace this with method choice below
        _insertSingleItem();
      }
    
      void _insertSingleItem() {
        String item = "Pig";
        int insertIndex = 2;
        _data.insert(insertIndex, item);
        _listKey.currentState.insertItem(insertIndex);
      }
    
      void _insertMultipleItems() {
        final items = ['Pig', 'Chichen', 'Dog'];
        int insertIndex = 2;
        _data.insertAll(insertIndex, items);
        // This is a bit of a hack because currentState doesn't have
        // an insertAll() method.
        for (int offset = 0; offset < items.length; offset++) {
          _listKey.currentState.insertItem(insertIndex + offset);
        }
      }
    
      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);
        };
        _listKey.currentState.removeItem(removeIndex, builder);
      }
    
      void _removeMultipleItems() {
        int removeIndex = 2;
        int count = 2;
        for (int i = 0; i < count; i++) {
          String removedItem = _data.removeAt(removeIndex);
          AnimatedListRemovedItemBuilder builder = (context, animation) {
            return _buildItem(removedItem, animation);
          };
          _listKey.currentState.removeItem(removeIndex, builder);
        }
      }
    }
    

    注意

    • 如果您的列表项包含任何有状态的小部件,那么您需要为它们提供密钥,以便系统可以跟踪它们。
    • 虽然我在写 Medium 文章之前写了这个答案,但我现在维护my answer on Medium。在那里查看最新更新。

    【讨论】:

    • 是否可以更新索引处的现有数据,而不是删除并重新添加?例如,我在索引处有一个文本,我想更改文本值。我该怎么做?
    • @Rakesh 您可以使用setState 并只更新数据列表。我扩展了我的答案here 来描述这一点。
    猜你喜欢
    • 2021-08-25
    • 2019-10-24
    • 2021-11-17
    • 2019-11-15
    • 2019-06-19
    • 1970-01-01
    • 2020-10-02
    • 2021-05-17
    • 2021-11-10
    相关资源
    最近更新 更多