Open In App

AnimatedList Flutter

Last Updated : 08 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

AnimatedList in Flutter is a dynamic list component that enables us to insert and remove elements dynamically. AnimatedList is a list that animates the items when they are removed or inserted enhancing the user experience.

As we all using ListView in Flutter lists for displaying a collection of items in a scrollable list format. In Real-Life scenarios, we sometimes need to add or remove items in between list. This sudden change in the list may confuse the user and lead to a bad user experience. The potential solution for this is to use AnimatedList in a flutter.

Prerequisites

  • Globalkey: GlobalKey is a type of key that is unique across the entire app.
  • ListView: It is a commonly used scrollable list of widgets in Flutter. It displays its children one after another in a scroll direction. It's especially useful when you're not sure how many widgets you'll be displaying, or if you're loading more data in real time.
  • Animations: You need a basic understanding of animations. Animations like SizeTransition, FadeTransition, SlideTransition, etc.

Given is the constructor for the AnimatedList Class

Constructor for AnimatedList Class

AnimatedList({
Key? key,
required AnimatedItemBuilder itemBuilder,
int initialItemCount ,
Axis scrollDirection ,
bool reverse ,
ScrollController? controller,
bool? primary,
ScrollPhysics? physics,
bool shrinkWrap,
EdgeInsetsGeometry? padding,
Clip clipBehavior
})

Properties of AnimatedList Widget

  • itemBuilder : It is Required Function that builds each items in list. It is called once for each item and during any animation affecting the item.
  • initialItemCount : It is used to specify the initial length of the list. It indicates that the number of items that list will start.
  • scrollDirection : It is used to specify the axis along with the scrolling occurs. It takes a value of Axis type, which can be either Axis.horizontal or Axis.vertical.
  • reverse : It is Boolean that specify whether the list should display its items in reverse order.
  • controller : It is used to control position to which scroll view is scrolled.
  • primary : It is Boolean that determines whether the widget is primary scroll view associated with parent PrimaryScrollController.
  • physics : It is used to determine how list should respond to user input and how it should over scroll. It takes Object of class that extends ScrollPhysics.
  • shrinkWrap : Is Boolean that determines whether the scroll view should shrink-wrap its content.
  • padding: It is used to provide padding to the AnimatedList. Takes EdgeInsets Object which defines padding.
  • clipBehavior : It is used to control how the widget should clip it's children. It takes a value from the Clip enum.

Simple Example of AnimatedList

In this example we are going to display list of persons using AnimatedList. Person will be having Name and Designation. we will first create a model and then using this create list of persons. Later we will be using this to display to user. user also can delete the items in list.

Step 1: Create a Project

Create a basic flutter project in IDE. the structure of project will look like following

01_project_Structure
Project Structure for AnimatedList Example

Once the project is created we need to perform following steps.

Step 2 : Create a model

Create Person Model for creating list of persons. This list is further used to diplay infomation in the form of List. Person Model is simple class with properties and Constructor.

Person.dart
class Person {
  final String name;
  final String designation;

  Person(this.name, this.designation);
}


Step 3 : Modify the main() function in codebase

we are modifying the main() function as per our need .

Dart
import 'package:animated_list_example/main_list_screen.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: MyApp(),
      debugShowCheckedModeBanner: false,
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MainListScreen();
  }
}

In the main() function, runApp() function is called which is taking the home as MyApp(). debugShowCheckedModeBanner is set to false , it will disable the debug banner from the app.

MyApp is a stateless widget which is returning MainListScreen widget

Step 4 : Create the MainListScreen Widget

This stateful widget that returns a new instance of _MainListScreenState when its createState mathod is called.

Dart
import 'package:animated_list_example/models/Person.dart';
import 'package:flutter/material.dart';

class MainListScreen extends StatefulWidget {
  const MainListScreen({super.key});

  @override
  State<MainListScreen> createState() => _MainListScreenState();
}

class _MainListScreenState extends State<MainListScreen> {
   @override
  Widget build(BuildContext context) {
    return Scaffold();
  }
}


Step 5 : Defining the GlobalKey and person list

Dart
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
  List<Person> people = [];


GlobalKey<AnimatedListState> is defined to keep reference to AnimatedListState and List<Person> to store the list of people.


Step 6 : Define Add Person Method

Dart
  void _addPerson(personName, personDesignation) {
    people.add(
      Person(personName, personDesignation),
    );
    _listKey.currentState!.insertItem(
      people.length - 1,
      duration: const Duration(milliseconds: 1000),
    );
  }


This method takes a person's name and designation as arguments, creates a new Person object, adds it to the people list, and inserts it into the AnimatedList.


Step 7 : Define remove person method

Dart
  void _removePerson(int index) {
    _listKey.currentState!.removeItem(
      index,
      (context, animation) => SizeTransition(
        sizeFactor: animation,
        child: const Card(
          margin: EdgeInsets.all(10),
          color: Colors.red,
          child: ListTile(
            title: Text(
              "Deleted",
              style: TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
                color: Colors.white,
              ),
            ),
          ),
        ),
      ),
      duration: const Duration(milliseconds: 500),
    );
    people.removeAt(index);
  }


This method takes an index as an argument, removes the person at that index from the AnimatedList and the people list.

Step 08 : Override the InitState() method

Dart
  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _addPerson('Manasi Konde', 'Web Developer');
      _addPerson('Rohan Chaudhary', 'Software Engineer');
      _addPerson('Vishal Chumbalkar', 'Software Engineer');
      _addPerson('Pranav Deshapande', 'Data Scientist');
      _addPerson('Jayesh Shinde', 'DevOps Engineer');
    });
    super.initState();
  }

This method is called once when the State object is created. It adds a few people to the list after the first frame has been displayed.


Step 9 : Implement AnimatedList

Dart
 AnimatedList(
        key: _listKey,
        initialItemCount: 0,
        itemBuilder: (context, index, animation) {
          return SizeTransition(
            key: UniqueKey(),
            sizeFactor: animation,
            child: Card(
              margin: const EdgeInsets.all(8.0),
              child: ListTile(
                tileColor: Colors.grey[200],
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                title: Text(
                  people[index].name,
                  style: const TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.green,
                  ),
                ),
                subtitle: Text(
                  people[index].designation,
                  style: const TextStyle(
                    fontSize: 15,
                    fontWeight: FontWeight.bold,
                    color: Colors.grey,
                  ),
                ),
                trailing: IconButton(
                  style: ButtonStyle(
                    backgroundColor:
                        MaterialStateProperty.all<Color>(Colors.black12),
                    shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                      RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10),
                      ),
                    ),
                  ),
                  icon: const Icon(Icons.delete, color: Colors.red),
                  onPressed: () {
                    _removePerson(index);
                  },
                ),
              ),
            ),
          );
        },
      ),


We are creating AnimatedList. The AnimatedList uses a GlobalKey to maintain state and animate items when they are inserted or removed. The itemBuilder function creates each item in the list, which is a Card containing a ListTile with person's details. The ListTile also includes a delete IconButton that removes the person from the list when pressed. The SizeTransition widget is used to animate the size of the items during insertion and removal.


Step 10 : Add FloatingActionButton

Dart
 FloatingActionButton(
        backgroundColor: Colors.white,
        onPressed: () {
          //pop up
          _showDialog();
          
        },
        child: const Icon(Icons.add, color: Colors.green),
)
   
// pop up dialog for adding new person   
TextEditingController nameController = TextEditingController();
TextEditingController designationController = TextEditingController();
 _showDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Add Person'),
          content: Column(
            children: <Widget>[
              TextField(
                controller: nameController,
                decoration: InputDecoration(hintText: "Enter Name"),
              ),
              TextField(
                controller: designationController,
                decoration: InputDecoration(hintText: "Enter Designation"),
              ),
            ],
          ),
          actions: <Widget>[
            ElevatedButton(
              onPressed: () {
                _addPerson(nameController.text, designationController.text);
                Navigator.of(context).pop();
              },
              child: Text('Add'),
            ),
          ],
        );
      },
    );


This button will show a dialog which will take Person name and person designation from the user once user clicked on add button _addPerson() method is called to add new person in the list.

Here is the Whole content of main_list_screen.dart

main.dart
import 'package:animated_list_example/models/Person.dart';
import 'package:flutter/material.dart';

class MainListScreen extends StatefulWidget {
  const MainListScreen({super.key});

  @override
  State<MainListScreen> createState() => _MainListScreenState();
}

class _MainListScreenState extends State<MainListScreen> {
  final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
  List<Person> people = [];
  TextEditingController nameController = TextEditingController();
  TextEditingController designationController = TextEditingController();

  void _addPerson(personName, personDesignation) {
    people.add(
      Person(personName, personDesignation),
    );
    _listKey.currentState!.insertItem(
      people.length - 1,
      duration: const Duration(milliseconds: 1000),
    );
  }

  void _removePerson(int index) {
    _listKey.currentState!.removeItem(
      index,
      (context, animation) => SizeTransition(
        sizeFactor: animation,
        child: const Card(
          margin: EdgeInsets.all(10),
          color: Colors.red,
          child: ListTile(
            title: Text(
              "Deleted",
              style: TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
                color: Colors.white,
              ),
            ),
          ),
        ),
      ),
      duration: const Duration(milliseconds: 500),
    );
    people.removeAt(index);
  }

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _addPerson('Manasi Konde', 'Web Developer');
      _addPerson('Rohan Chaudhary', 'Software Engineer');
      _addPerson('Vishal Chumbalkar', 'Software Engineer');
      _addPerson('Pranav Deshapande', 'Data Scientist');
      _addPerson('Jayesh Shinde', 'DevOps Engineer');
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GeeksForGeeks'),
      ),
      body: AnimatedList(
        key: _listKey,
        initialItemCount: 0,
        itemBuilder: (context, index, animation) {
          return SizeTransition(
            key: UniqueKey(),
            sizeFactor: animation,
            child: Card(
              margin: const EdgeInsets.all(8.0),
              child: ListTile(
                tileColor: Colors.grey[200],
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                title: Text(
                  people[index].name,
                  style: const TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.green,
                  ),
                ),
                subtitle: Text(
                  people[index].designation,
                  style: const TextStyle(
                    fontSize: 15,
                    fontWeight: FontWeight.bold,
                    color: Colors.grey,
                  ),
                ),
                trailing: IconButton(
                  style: ButtonStyle(
                    backgroundColor:
                        MaterialStateProperty.all<Color>(Colors.black12),
                    shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                      RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10),
                      ),
                    ),
                  ),
                  icon: const Icon(Icons.delete, color: Colors.red),
                  onPressed: () {
                    _removePerson(index);
                  },
                ),
              ),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.white,
        onPressed: () {
          //pop up
          _showDialog();
         
        },
        child: const Icon(Icons.add, color: Colors.green),
      ),
    );
  }

  // pop up dialog for adding new person
  _showDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Add Person'),
          content: Column(
            children: <Widget>[
              TextField(
                controller: nameController,
                decoration: InputDecoration(hintText: "Enter Name"),
              ),
              TextField(
                controller: designationController,
                decoration: InputDecoration(hintText: "Enter Designation"),
              ),
            ],
          ),
          actions: <Widget>[
            ElevatedButton(
              onPressed: () {
                _addPerson(nameController.text, designationController.text);
                Navigator.of(context).pop();
              },
              child: Text('Add'),
            ),
          ],
        );
      },
    );
  }
}

Output:

Conclusion

In this article we have created a simple app which displays list of persons having the name and designation using AnimatedList , we have used SizedTransition animation. We have also looked at the constructor and properties of AnimatedList in flutter.


Next Article
Article Tags :

Similar Reads