Noam
Noam

Reputation: 535

How to animate container inside a list

I've a list of containers and i want to animate the container.

For example, change his height/width, and change the content of the container.

What I've done so far is this:

containerHeight =  MediaQuery.of(context).size.height * 0.20;
body: Container(
            child: ListView.builder(
              itemCount: data.length,
              itemBuilder: (BuildContext context, int index) {
                return Padding(
          padding: const EdgeInsets.all(15.0),
          child: Container(
            color: Colors.black,
            height: containerHeight,
            child: IconButton(
              icon: Icon(Icons.list),
              color: Colors.white,
              onPressed: () {
                setState(() {
                 containerHeight =  MediaQuery.of(context).size.height * 0.35;
                });
              },
            ),
          ),
        );
              },
            ),

I'm planning to use AnimatedContainer, but even now before used it, if I press the button nothing happend

Upvotes: 5

Views: 3293

Answers (1)

Ajil O.
Ajil O.

Reputation: 6892

This is how I got it to work. I just replaced the container with an Animated Container

class _HomePageState extends State<HomePage> {
  List<String> dataList = ['Andrew', 'Test', 'Data', 'Random'];
  double containerHeight;
  bool expanded = false;

  @override
  Widget build(BuildContext context) {
    containerHeight = expanded
        ? MediaQuery.of(context).size.height * 0.20
        : MediaQuery.of(context).size.height * 0.30;
    return Scaffold(
      appBar: AppBar(
        title: Text('Test App'),
      ),
      body: ListView.builder(
        itemCount: dataList.length,
        itemBuilder: (context, index) {
          return AnimatedContainer(
            curve: Curves.easeOut,
            duration: Duration(milliseconds: 400),
            color: Colors.red,
            height: containerHeight,
            margin: EdgeInsets.all(8),
            child: Center(
              child: Text(
                dataList.elementAt(index),
                style: TextStyle(
                  color: Colors.white,
                ),
              ),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(onPressed: () {
        setState(() {
          expanded = !expanded;
        });
      }),
    );
  }
}

Output

enter image description here

EDIT

If you want to collapse only the element you are tapping on, it would be better if you create a class which can hold the current state of your container.

class DataModel {
  String title;
  bool expanded;

  DataModel(this.title) {
    expanded = false;
  }
}

Here, expanded will keep track of whether the container should be large or small.

Now refactoring the previous code a bit

class _HomePageState extends State<HomePage> {


  // Initialize DATA MODEL list with some random values.
  List<DataModel> dataList = ['Andrew', 'Test', 'Data', 'Random']
      .map<DataModel>((s) => DataModel(s))
      .toList();

  double containerHeight;

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text('Test App'),
      ),
      body: ListView.builder(
        itemCount: dataList.length,
        itemBuilder: (context, index) {

          DataModel item = dataList.elementAt(index);

          // Check if the item is expanded or not and set size accordingly
          containerHeight = item.expanded
              ? MediaQuery.of(context).size.height * 0.20
              : MediaQuery.of(context).size.height * 0.30;

          return GestureDetector(
            onTap: (){
              // On tap reverse the expanded state of the data which will resize
              // the widget as setState is being called
              setState(() {
                item.expanded = !item.expanded;
              });
            },
            child: AnimatedContainer(
              curve: Curves.easeOut,
              duration: Duration(milliseconds: 400),
              color: Colors.red,
              height: containerHeight,
              margin: EdgeInsets.all(8),
              child: Center(
                child: Text(
                  dataList.elementAt(index).title,
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

Upvotes: 7

Related Questions