Flutter — Как столбец ограничивает свою высоту внутри представления списка, когда его значение по умолчанию mainAxisSize = max?

#flutter

Вопрос:

Какая магия позволяет ListView ограничивать свои дочерние элементы их минимальным внутренним размером во время компоновки?


Согласно Column алгоритму компоновки, он старается быть как можно выше (по умолчанию).

Внутри а ListView во performLayout время ограничения роста для Sliver ребенка есть double.INFINITY (если я не ошибаюсь).

Как Column ограничить его высоту до его внутренней высоты (т. Е. Минимума, необходимого для размещения его дочерних элементов), когда входящее ограничение высоты внутри a ListView равно бесконечности?

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

Раскомментирование child: MyColumn() при комментировании child:ListView() показывает Column расширение до обычной максимальной высоты. Но внутри а ListView он волшебным образом ограничен своей минимальной высотой. Мне интересно, как это делается.

 import 'package:flutter/material.dart';

class FlexInListViewPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Column in ListView'),
      ),
      body: Container(
        decoration: BoxDecoration(
          border: Border.all(width: 3, color: Colors.lightGreenAccent)
        ),
        //child: MyColumn() // ← uncomment while commenting out ↓ to see Column amp; its default height
        child: ListView(// imposes tight constraint of screen width to children
          children: [ /// RenderSliverList performLayout doesn't impose a constraint height during layout
            /// but asks children to report back size after layout complete
            /// this allows ListView to pass a height constraint to Column
            Container(child: Text('child'), color: Colors.yellowAccent,),
            Container(child: MyColumn(), color: Colors.orangeAccent.withOpacity(.5),)
          ],
        ),
      ),
    );
  }
}

class MyColumn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    /// Column
    /// 1: layout fixed-height (zero flex factor) children in unbounded vertical space
    /// 2: Calculate/reserve remaining space for flex-height children
    /// 3: No flex children, skip flex-kids layout
    /// 4: Width is either widest child, or width imposed by parent (ListView: screen width)
    /// 5: Height of Column is by default mainAxisSize: max, try to fill all vert. space
    /// 5: If mainAxisSize: min amp; incoming vert. constraints allow,
    /// height of Column is sum of children heights
    return Column(
      children: [
        Container(child: Text('inside Column'), color: Colors.lightBlueAccent.withOpacity(.3),)
      ],
    );
  }
}
 

Что показывает приведенный выше код:

Столбец внутри списка, магически ограниченный

Примечания

Я видел код, в parentUsesSize котором размер макета передается от дочерних элементов к родительским, но я не понимаю, как Column можно увеличить размер до минимальной высоты, когда его ограничение неограниченно. Передается ли какая-то неочевидная информация, что-то вроде «минимально необходимый размер макета» или «желаемый размер макета»?

Ответ №1:

я предполагаю, что это то, чего вы хотите достичь, внутри вашего списка добавляйте shrinkWrap: true и primary: false

 ListView(// imposes tight constraint of screen width to children
            primary: false,
            shrinkWrap: true,
            children: [ /// RenderSliverList performLayout doesn't impose a constraint height 
            during layout
            /// but asks children to report back size after layout complete
            /// this allows ListView to pass a height constraint to Column
            Container(child: Text('child'), color: Colors.yellowAccent,),
            Container(child: MyColumn(), color: Colors.orangeAccent.withOpacity(.5),)
          ],
 

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

1. Спасибо за ответ, но я не пытаюсь уменьшить размер представления списка. Я ищу объяснение того , как Column не расширяется, чтобы занять все ListView , что по умолчанию, согласно его алгоритму компоновки, как я понимаю, должно быть.