Home > Mobile >  Clip Stack children
Clip Stack children

Time:10-12

How to clip Stack children within it's size.

In this image there are 3 grid-Items using orange color and every item using InkWell to use hover-Method to Align on Stack. While hover:false the Pop PoP Widget won't be visible to the UI. With align property it works, but as you can see the Right Top GridItem's item:2 pop POp widget is visible outside the Stack<Griditem> and I want to make it invisible outside the stack. I've tested using clipBehavior: with every Clip enums.

I want to hide the Pop POp widget while it is outside the Stack and yes I need this pop-up effect.

For Flutter web and I'm using Flutter V2.5.2

Current Layout with Issue
Issue Image

Full Code to reproduce the issue

import 'package:flutter/material.dart';
void main() => runApp(
      const MaterialApp(
        home: Appp(),
      ),
    );

class Appp extends StatelessWidget {
  const Appp({Key? key}) : super(key: key);

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

class BodyX extends StatelessWidget {
  const BodyX({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: LayoutBuilder(
      builder: (context, constraints) {
        return GridView.count(
          crossAxisCount: 2,
          children: [
            ...List.generate(
              3,
              (index) => GridItem(
                key: UniqueKey(),
                maxWidth: constraints.maxWidth / 2,
              ),
            ),
          ],
        );
      },
    ));
  }
}

class GridItem extends StatefulWidget {
  const GridItem({
    Key? key,
    required this.maxWidth,
  }) : super(key: key);
  final double maxWidth;
  @override
  State<GridItem> createState() => _AppXState();
}

class _AppXState extends State<GridItem> {
  bool _isHovered = false;

  @override
  Widget build(BuildContext context) {
    print("ItemWidth : ${widget.maxWidth}");
    return SizedBox(
      //though it wont effect here,
      // just finding the size of Grid because it will 1x1
      width: widget.maxWidth,
      height: widget.maxWidth,
      child: InkWell(
        onTap: () {},
        hoverColor: Colors.black,
        onHover: (value) {
          setState(() {
            _isHovered = value;
          });
        },
        child: Stack(
          clipBehavior: Clip.antiAliasWithSaveLayer,
          children: [
            Container(
              color: Colors.deepOrange.withOpacity(.2),
            ),
            AnimatedAlign(
              alignment: Alignment(0, _isHovered ? .7 : 2),
              child: Container(
                padding: const EdgeInsets.all(22),
                color: Colors.greenAccent,
                child: const Text(
                  "Pop POp",
                ),
              ),
              duration: const Duration(
                milliseconds: 200,
              ),
            )
          ],
        ),
      ),
    );
  }
}

CodePudding user response:

If you don't want a Widget to draw beyond its layout size, you can use ClipRect to clip it.

In your case, you can wrap ClipRect on your Stack, like so:

ClipRect(
  child: Stack(
    children: ...
  ),
)

Further more, you can use ClipRRect to clip a rounded rectangle shape (circular border) or ClipPath to clip a custom shape, like a triangle. You can read more about these widgets in the official docs.

  • Related