skip to Main Content

I’m trying to add an overlay to a GridView in Flutter. The effect I want to achieve is for my grid to initially appear blocked, and then, for example after a button click, remove the overlay and show the underlying content. However, every attempt I make results in a full-screen overlay or I must declare a fixed height but for a GridView that is adaptive is not a great choice.

This is what I am trying to do:

mockup

But my widgets look like this:

enter image description here

That’s my code:

Stack(
 children: [
    GridView.builder(
    shrinkWrap: true,
    physics: const NeverScrollableScrollPhysics(),
    gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
    crossAxisSpacing: 12,
    mainAxisSpacing: 12), 
    itemCount: myList.length,
    itemBuilder: (
       context,
       index,
    ) {
    return Container(
       width: 50, 
      height:50,
    decoration: BoxDecoration(
    border: Border.all(color: Colors.black)
  ),
    
}),

Center(
   child: Container(
   width: double.infinity, 
   color: Colors.grey,
  ),
)],
),

Thank you all

3

Answers


  1. Try this version; it might resolve your problem:

    The GridView is wrapped in a Visibility widget that controls its visibility based on the boolean variable isOverlayVisible. The overlay is implemented using a semi-transparent Container positioned at the same level as the GridView. A button (an ElevatedButton in this case) is positioned using the Positioned widget to toggle the isOverlayVisible boolean, thus controlling the visibility of the overlay.

    bool isOverlayVisible = true; // Define a boolean to toggle the overlay
    
    Stack(
      children: [
        // Your GridView wrapped in a Visibility widget to control its visibility
        Visibility(
          visible: !isOverlayVisible,
          child: GridView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
              crossAxisSpacing: 12,
              mainAxisSpacing: 12,
            ),
            itemCount: myList.length,
            itemBuilder: (context, index) {
              return Container(
                width: 50,
                height: 50,
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.black),
                ),
                // Your grid item content here
              );
            },
          ),
        ),
        // Semi-transparent overlay container
        Container(
          color: Colors.black.withOpacity(0.5), // Adjust opacity as needed
        ),
        // Your button or trigger to toggle the overlay
        Positioned(
          top: 20, // Adjust position as needed
          left: 20, // Adjust position as needed
          child: ElevatedButton(
            onPressed: () {
              setState(() {
                isOverlayVisible = !isOverlayVisible; // Toggle overlay visibility
              });
            },
            child: Text(isOverlayVisible ? 'Show Content' : 'Hide Content'),
          ),
        ),
      ],
    );
    
    
    
    Login or Signup to reply.
  2. You almost there:

    You can just wrap that container with positioned widget to force it to cover the whole stack:

    Positioned(
    
    // how far is the container from each side
    
    left : 0, 
    top : 0,
    bottom : 0,
    right : 0,
    
    child: Container(color: Colors.grey),
    
    )
    

    If you got the above snippet of code, it’s the same as that named constructor:

    Positioned.fill(
    child: Container(color: Colors.grey)
    )
    

    This named constructor just use a zero for each attribute top , left, right and bottom.

    Login or Signup to reply.
  3. actually there is a Widget called Overlay which is made for this:

    Here’s a code :

    class OverlayExampleWidget extends StatefulWidget {
      const OverlayExampleWidget({super.key});
    
      @override
      State<OverlayExampleWidget> createState() => _OverlayExampleWidgetState();
    }
    
    class _OverlayExampleWidgetState extends State<OverlayExampleWidget> {
      bool isLocked = true;
      void unLockContent() {
        setState(() {
          isLocked = !isLocked;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Overlay(
            initialEntries: <OverlayEntry>[
              OverlayEntry(
                builder: (context) {
                  return Positioned(
                    top: 0,
                    right: 0,
                    left: 0,
                    bottom: 0,
                    child: GridView.builder(
                      shrinkWrap: true,
                      physics: const AlwaysScrollableScrollPhysics(),
                      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 3,
                        crossAxisSpacing: 12,
                        mainAxisSpacing: 12,
                      ),
                      itemCount: 30,
                      itemBuilder: (
                        context,
                        index,
                      ) {
                        return Container(
                          width: 50,
                          height: 50,
                          decoration: BoxDecoration(
                            border: Border.all(color: Colors.black),
                          ),
                        );
                      },
                    ),
                  );
                },
              ),
              OverlayEntry(
                builder: (context) {
                  return GestureDetector(
                    onTap: () {
                      unLockContent();
                    },
                    child: isLocked
                        ? Positioned(
                            top: 0,
                            right: 0,
                            bottom: 0,
                            left: 0,
                            child: Container(
                              color: Colors.black.withOpacity(0.3),
                              child: const Center(
                                child: Icon(
                                  Icons.lock,
                                  size: 50,
                                ),
                              ),
                            ),
                          )
                        : null,
                  );
                },
              ),
            ],
          ),
        );
      }
    }
    

    You can use the same Positioned with Stack also

    Hope that’s help !!!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search