Флаттер, как работает система отсечения теней?

#flutter #flutter-layout

#флаттер #флаттер-макет

Вопрос:

Я так запутался в том, как работает система отсечения в Flutter.


Итак, я начну с этого примера, ни одна тень не была отсечена.

Даже тень была переполнена из своего собственного или родительского контейнера.

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

введите описание изображения здесь


Теперь, если я добавлю больше ShadowBox() , пока он не переполнится, вся тень будет обрезана.

Например:

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

введите описание изображения здесь


Теперь даже я меняюсь Row на be SingleChildScrollView или List он все еще обрезается, но не переполняется

 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(),
        ),
      ),
    ],
  ),
)
  

введите описание изображения здесь


Итак, вопрос в том, как это работает, и как я могу предотвратить отсечение этих теней?

Или это недостаток дизайна самого Flutter?

Ответ №1:

Я запустил это в проблеме Flutter.

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

Насколько я понимаю, поведение клипа по умолчанию Container Row Column отличается от ListView и внутреннего Overflow .

Итак, у нас есть обходной путь путем добавления clipBehaviour: Clip.none в ListView.

Комментарии:

1. Спасибо! Также работает с SingleChildScrollView.

Ответ №2:

Редактировать: чтобы получить перекрывающиеся тени и не отсекать, вы можете попробовать:

В ShadowBox() виджете,

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

Что касается того, почему он обрезается?

В движке Flutter отсечение тени является поведением по умолчанию.

Если вы углубитесь в код, вы обнаружите, что ширина / высота тени не учитываются при отображении дочерних элементов в ListView или любом виджете. Так что вы должны позаботиться об этом.

Тогда почему она не отсекается в строке / столбце?

В строках и столбцах отсечение не отображается, поскольку оно принимает высоту строки / столбца в соответствии с максимальной высотой / шириной родительского элемента. Таким образом, его высота / ширина равна Max / Infinity.

Итак, если вы увеличите ширину и высоту ListView() родительского Container() виджета, отсечения также не произойдет.

Комментарии:

1. Большое вам спасибо за ответ, но это все еще не объясняет, почему он обрезан. Я не нашел никакого кода внутри ListView, который отсекал тень. И если ListView обрезан, почему строка переполнения и столбец также обрезаны.

2. Боюсь, это все еще не решение моей проблемы. Как вы видите на изображении, тень boxShadow перекрывается с тенью следующей boxShadow. Добавление дополнения предотвратит это.

3. О, конечно, я обновил ответ, чтобы получить перекрывающиеся тени и отсутствие отсечения в listview

4. Я также добавил объяснение того, почему обрезается тень.

5. Я прошу прощения, но ответ все еще немного неоднозначен, поэтому он не работает, и ответом является сам движок Flutter по умолчанию. Так что я до сих пор не знаю причины, и если это сделано намеренно или намеренно.