Search code examples
flutterdart

How can I create a dropdown menu that shows a staggered grid view?


I want to put my staggered grid view in a dropdown menu like my sketch below. I'm not sure how else to describe it. If you could lead me in the right direction or show me how I can achieve this it would me much appreciated!

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

example

Here's my code for the staggered grid view:

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:transparent_image/transparent_image.dart';

class Grid extends StatefulWidget {
  @override
  _GridState createState() => _GridState();
}

class _GridState extends State<Grid> {
  List<String> imageList = [
    'https://i.pinimg.com/originals/78/c1/80/78c1805437afbfa026b04d550385d118.jpg',
    'https://i.pinimg.com/originals/78/c1/80/78c1805437afbfa026b04d550385d118.jpg',
    'https://i.pinimg.com/originals/78/c1/80/78c1805437afbfa026b04d550385d118.jpg',
    'https://i.pinimg.com/originals/78/c1/80/78c1805437afbfa026b04d550385d118.jpg',
  ];

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: ListView(
          children: [
            ListTile(title: Center(
              child: Text('Category 1',
                style: TextStyle(
                    fontSize: 60),
              ),
            ),
            ),


            Container(
              margin: EdgeInsets.all(10),
              child: Container(
                child: StaggeredGridView.countBuilder(
                  shrinkWrap: true,
                  primary: false,
                  crossAxisCount: 2,
                  crossAxisSpacing: 10,
                  mainAxisSpacing: 12,
                  itemCount: imageList.length,
                  itemBuilder: (context, index) {
                    return Container(
                      decoration: BoxDecoration(
                        color: Colors.transparent,
                        borderRadius: BorderRadius.all(
                          Radius.circular(15),
                        ),
                      ),
                      child: ClipRRect(
                        borderRadius: BorderRadius.all(
                          Radius.circular(15),
                        ),
                        child: FadeInImage.memoryNetwork(
                            placeholder: kTransparentImage,
                            image: imageList[index],
                            fit: BoxFit.cover),
                      ),
                    );
                  },
                  staggeredTileBuilder: (index) {
                    return StaggeredTile.count(1, index.isEven ? 1.2 : 1.8);
                  },
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}


Solution

  • You can create your widget like this:

    import 'package:flutter/material.dart';
    
    class MainPage extends StatelessWidget {
      static late double width;
      static late double height;
    
      @override
      Widget build(BuildContext context) {
        width = MediaQuery.of(context).size.width;
        height = MediaQuery.of(context).size.height;
        return Scaffold(
          body: ListView.builder(
            itemCount: 10,
            itemBuilder: (context, index) => GridMenu(),
          ),
        );
      }
    }
    
    class GridMenu extends StatefulWidget {
      const GridMenu({Key? key}) : super(key: key);
    
      @override
      _GridMenuState createState() => _GridMenuState();
    }
    
    class _GridMenuState extends State<GridMenu> {
      bool _collapse = false;
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            GestureDetector(
              onTap: () => setState(() {
                _collapse = !_collapse;
              }),
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Row(
                  children: [
                    Expanded(
                        child: Text(
                      'Category',
                      style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                    )),
                    Icon(_collapse
                        ? Icons.keyboard_arrow_up
                        : Icons.keyboard_arrow_down),
                  ],
                ),
              ),
            ),
            AnimatedContainer(
              duration: Duration(milliseconds: 500),
              width: MainPage.width,
              height: _collapse ? MainPage.width : 0,
              child: GridView.builder(
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                ),
                itemCount: 20,
                itemBuilder: (context, index) => GestureDetector(
                  onTap: () {
                    /** choose item **/
                  },
                  child: Container(
                    margin: EdgeInsets.all(16),
                    color: Colors.green,
                  ),
                ),
              ),
            ),
          ],
        );
      }
    }
    

    I hope this useful for you.