Flutter, How shadow clipping system work?

Viewed 268

I'm so confused about how the clipping system in Flutter works.


So I will start with this example, Non of the shadow has been clipped.

Even the shadow was overflow from its self or its parent container.

Container(
  child: Column(
    children: [
      Text("test"),
      Container(
        margin: paddingTheme.edgeInsets,
        child: Row(
          children: [
            ShadowBox(),
            ShadowBox(),
            ShadowBox(),
          ],
        ),
      ),
    ],
  ),
)

enter image description here


Now if I add more ShadowBox() until it overflows, All the shadow will be clipped.

For example:

Container(
  child: Column(
    children: [
      Text("test"),
      Container(
        margin: paddingTheme.edgeInsets,
        child: Row(
          children: [
            ShadowBox(),
            ShadowBox(),
            ShadowBox(),
            ShadowBox(), // ADD THIS
          ],
        ),
      ),
    ],
  ),
)

enter image description here


Now even I change Row to be SingleChildScrollView or List it's still clipped, But not overflow

Container(
  child: Column(
    children: [
      Text("test"),
      Container(
        margin: paddingTheme.edgeInsets,
        child: ListView.builder( // CHANGE FROM ROW TO LIST
          scrollDirection: Axis.horizontal,
          itemCount: 5,
          itemBuilder: (c, i) => ShadowBox(),
        ),
      ),
    ],
  ),
)

enter image description here


So the question is how it's work, And how can I prevent these shadows to be clipped?

Or it's a design flaw of Flutter itself?

2 Answers

I had fire this in the Flutter's issue.

https://github.com/flutter/flutter/issues/67858

As I understand from now, The default ClipBehaviour of Container Row Column is different from ListView and internal Overflow.

So we have a workaround by adding clipBehaviour: Clip.none to the ListView.

Edit: To get the overlap shadows and no clipping, you can try:

In ShadowBox() widget,

Container(
       height: 100,
       width: 100,
       margin: EdgeInsets.only(top: 20,bottom: 20), <-----
       decoration:BoxDecoration(
            color: Colors.white,
            boxShadow: [BoxShadow(color: Colors.blue,blurRadius: 12)]
       ),
),

As for why it is clipped?

In Flutter engine, clipping the shadow is default behavior.

If you go deep in code you will find that shadow's width/height is not taken into account while rendering children in ListView or any widget. So you have to take care of it.

Why is it not clipping in Row/Column then?

In Rows and columns, no clipping is visible because it assumes the height of Row/Column as per the parent's max height/width. So it's height/width is at Max/Infinity.

So if you increase the width and height of the ListView()'s parent Container() widget, clipping will not happen as well.

Related