Search code examples
dartflutterflutter-animatedlist

How to clear all items from an AnimatedList in Flutter


I was trying to preproduce all of the update operations on an AnimatedList like I have done for a RecyclerView adapter in Android. But when I got to clearing all of the data, I couldn't figure out how to do it.

If I do this

setState(() {
  _data.clear();
});

then the backing data is cleared but the GlobalKey's current state still doesn't know about the change, and there is no clear() method on it.

Supplemental code

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(
            'Clear all items',
            style: TextStyle(fontSize: 20),
          ),
          onPressed: () {
            _clearAllItems();
          },
        )
      ],
    );
  }

  Widget _buildItem(String item, Animation animation) {
    return SizeTransition(
      sizeFactor: animation,
      child: Card(
        child: ListTile(
          title: Text(
            item,
            style: TextStyle(fontSize: 20),
          ),
        ),
      ),
    );
  }

  void _clearAllItems() {
    _data.clear();
    // no such method
    _listKey.currentState.clear();
  }

}

Solution

  • You have to remove item in _listKey.currentState manually

    Sample code:

    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(
                'Clear all items',
                style: TextStyle(fontSize: 20),
              ),
              onPressed: () {
                _clearAllItems();
              },
            )
          ],
        );
      }
    
      Widget _buildItem(String item, Animation animation) {
        return SizeTransition(
          sizeFactor: animation,
          child: Card(
            child: ListTile(
              title: Text(
                item,
                style: TextStyle(fontSize: 20),
              ),
            ),
          ),
        );
      }
    
      void _clearAllItems() {
        for (var i = 0; i <= _data.length - 1; i++) {
          _listKey.currentState.removeItem(0,
              (BuildContext context, Animation<double> animation) {
            return Container();
          });
        }
        _data.clear();
      }
    }