'How to Expand ( Increase the size of Container ) the particular container on clicked in flutter

  • Container Size depends on the widget's child length
  • I want all things in the mobile screen height not the inner child scroll or outer

I expected output like below -

enter image description here

what I am getting -

enter image description here

import 'package:flutter/material.dart';

class ExpandableContainer extends StatefulWidget {
  const ExpandableContainer({Key? key}) : super(key: key);

  @override
  State<ExpandableContainer> createState() => _ExpandableContainerState();
}

class _ExpandableContainerState extends State<ExpandableContainer> {
  int selectedIndex = -1;
  List dataList = [
    {
      "title": "Title 1",
      "items": [
        'Item 1',
        'Item 2',
        'Item 3',
        'Item 4',
      ],
    },
    {
      "title": "Title 2",
      "items": [
        "Item 1",
        "Item 2",
        "Item 3",
        "Item 4",
        "Item 5",
        "Item 6",
        "Item 7",
        "Item 8",
      ],
    },
    {
      "title": "Title 3",
      "items": [
        "Item 1",
        "Item 2",
        "Item 3",
        "Item 4",
      ],
    },
    {
      "title": "Title 4",
      "items": [
        "Item 1",
        "Item 2",
        "Item 3",
        "Item 4",
        "Item 5",
        "Item 6",
        "Item 7",
        "Item 8",
        "Item 9",
        "Item 10",
      ],
    },
    {
      "title": "Title 5",
      "items": [
        "Item 1",
        "Item 2",
        "Item 3",
        "Item 4",
        "Item 5",
        "Item 6",
        "Item 7",
      ],
    },
  ];

@override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Colors.white,
      body: SizedBox(
        height: size.height,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: List.generate(
            dataList.length,
            (index) => GestureDetector(
              onTap: () => setState(() {
                selectedIndex = index;
              }),
              child: Container(
                height: size.height / dataList.length,
                width: size.width,
                padding: const EdgeInsets.fromLTRB(32.0, 16.0, 0.0, 16.0),
                // alignment: Alignment.center,
                decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border.all(width: 8.0, color: Colors.grey),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      dataList[index]["title"].toUpperCase(),
                      style: const TextStyle(
                        fontSize: 38.0,
                        color: Colors.black,
                        fontWeight: FontWeight.w900,
                        letterSpacing: -2.0,
                      ),
                    ),
                    for (var item in dataList[index]["items"])
                      Text(
                        selectedIndex == index ? item : "",
                        style: TextStyle(
                          fontSize: 20.0,
                          color: Colors.black,
                          height: selectedIndex == index ? 1.5 : 0.0,
                        ),
                      ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}


Solution 1:[1]

enter image description here

     List<String> category = [
        "HealthCare",
        "Food & Drink",
        "Beauty",
        "Baby & kids",
        "Homeware"
      ];
      List<Color> color = [
        Colors.lightBlueAccent,
        Colors.green.shade700,
        Colors.pinkAccent.shade100,
        Colors.blueAccent,
        Colors.amber,
      ];
      List<Color> textColor = [
        Colors.blueAccent.shade700,
        Colors.amber,
        Colors.pinkAccent.shade700,
        Colors.pinkAccent.shade100,
        Colors.white,
      ];
    
      int? selectedIndex;
      List<dynamic> dataList = [
        {
          "title": "Title 1",
          "items": [
            'Item 1',
            'Item 2',
            'Item 3',
            'Item 4',
          ],
        },
        {
          "title": "Title 2",
          "items": [
            "Item 1",
            "Item 2",
            "Item 3",
            "Item 4",
            "Item 5",
            "Item 6",
            "Item 7",
            "Item 8",
          ],
        },
        {
          "title": "Title 3",
          "items": [
            "Item 1",
            "Item 2",
            "Item 3",
            "Item 4",
          ],
        },
        {
          "title": "Title 4",
          "items": [
            "Item 1",
            "Item 2",
            "Item 3",
            "Item 4",
            "Item 5",
            "Item 6",
            "Item 7",
            "Item 8",
            "Item 9",
            "Item 10",
          ],
        },
        {
          "title": "Title 5",
          "items": [
            "Item 1",
            "Item 2",
            "Item 3",
            "Item 4",
            "Item 5",
            "Item 6",
            "Item 7",
          ],
        },
      ];

 Scaffold(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.max,
        children: [
          ...category.map(
            (index) => Expanded(
              flex: selectedIndex==category.indexOf(index) ? (dataList[category.indexOf(index)]["items"].length/3).ceil(): 1,
              child: GestureDetector(
                onTap: () {
                  print(dataList[category.indexOf(index)]["items"].toString());
                  print("tap");
                  setState(() {
                    selectedIndex = category.indexOf(index);
                  });
                },
                child: Container(
                  color: color[category.indexOf(index)],
                  child: Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,

                      children: [
                        Text(
                          index.toUpperCase(),
                          style: TextStyle(
                              fontSize: 36,
                              fontWeight: FontWeight.bold,
                              color: textColor[category.indexOf(index)]),
                        ),
                        selectedIndex == category.indexOf(index)
                            ? Column(
                                children: [
                                  ...dataList[category.indexOf(index)]
                                          ["items"]
                                      .map(
                                    (e) => Text(e),

                                  ),
                                  // ListTile(title:Text(dataList[category.indexOf(index)]["items"].toString()))
                                ],
                              )
                            : SizedBox(),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );

Solution 2:[2]

Please use ExpansionTile for expansion

              ExpansionTile(
                      iconColor:Colors.blue,
                      textColor:Colors.black,
                      title:  Text('Privacy Policy',style:  TextStyle(fontSize: 16)),

                      children: [
                        ListTile(
                          title:  Text('item1',textAlign: justifyText,),
                        ),

                        ListTile(
                          title:  Text('item2',textAlign: justifyText,),
                        ),


                        ListTile(
                          title:  Text('item3',textAlign: justifyText,),
                        ),


                        ListTile(
                          title:  Text('item4',textAlign: justifyText,),
                        ),

                      ],
                    ),

Solution 3:[3]

Try this you can test this on dartpad its so now the one is hindering the size was on the container so if you select a certain index make the container height to null so that it will wrap the results inside.

return Scaffold(
      backgroundColor: Colors.white,
      body: SizedBox(
        child: ListView.builder(
          shrinkWrap: true,
          itemCount: dataList.length,
          itemBuilder:(context,index)
          =>GestureDetector(
              onTap:(){
                setState((){
                 selectedIndex = index;
                 print( dataList[index]['items'].map((e)=> e).toList());
                });
              },
              child: Container(
                 height:  selectedIndex == index ? null 
                  : size.height / dataList.length,
                width: size.width,
                padding: const EdgeInsets.fromLTRB(32.0, 16.0, 0.0, 16.0),
                // alignment: Alignment.center,
                decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border.all(width: 8.0, color: Colors.grey),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      dataList[index]["title"].toUpperCase(),
                      style: const TextStyle(
                        fontSize: 38.0,
                        color: Colors.black,
                        fontWeight: FontWeight.w900,
                        letterSpacing: -2.0,
                      ),
                    ),
                    
                      ...dataList[index]['items'].map((e)=> 
                      selectedIndex == index ?
                        Text(
                        e,
                        style: TextStyle(
                          fontSize: 20.0,
                          color: Colors.black,
                          height: selectedIndex == index ? 1.5 : 0.0,
                        ) ,
                      ) : Container(),).toList()
                    
                    
                  ],
                ),
              ),
            
          ),
          ),
      ),
    );

Solution 4:[4]

Solution No 1

enter image description here

To achieve this you can use ExpansionTile class,

This widget is typically used with ListView to create an "expand / collapse" list entry. When used with scrolling widgets like ListView, a unique PageStorageKey must be specified to enable the ExpansionTile to save and restore its expanded state when it is scrolled in and out of view.

this is the link about ExpansionTile

https://api.flutter.dev/flutter/material/ExpansionTile-class.html#:~:text=ExpansionTile%20class%20Null%20safety,expand%20%2F%20collapse%22%20list%20entry.

and this is the demo example link how to do it

https://rrtutors.com/tutorials/Expandable-Listview-Flutter-ExpansionTile

Solution No 2

Use ExpandableGroup

enter image description here

To achieve this you can use ExpandableGroup

this is the link about ExpandableGroup

https://pub.dev/packages/expandable_group

if you don't want to use plugin , just inspect this plugin code , it has simple logic

Solution 5:[5]

You can use expansion tile but if the existing expansion tile does not provide the view required for your project, you can create your own custom expansion tile widget.

Like

app_expansion_tile

Solution 6:[6]

You should use expansion tile, as far as i have saw in your image you don't want it to be scrollablle, what i suggest is to make a limitation on the expansiontile class or the child, then set restriction limit to with and height and make it be responsive.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hammad Ali
Solution 2 Vishal Singh
Solution 3 Arbiter Chil
Solution 4
Solution 5 Abhishek Thakur
Solution 6 Arjay