Flutter: автоматическая вертикальная высота в ListView.builder

Я пытаюсь показать некоторые карты с ListView.builder
Я хочу автоматически установить высоту каждой карточки в соответствии с ее дочерним содержимым.

class HomePage extends StatelessWidget {
 Widget _buildListItems(BuildContext context, DocumentSnapshot document) {
  return Center(
   child: Card(
    child: Column(
      children: <Widget>[
        ListTile(
          title: Text(document['title']),
          subtitle: Text(document['subtitle']),
        ),
        Expanded(
          child: Container(
            padding: EdgeInsets.all(20.0),
            child: Text(
              document['summary'],
              softWrap: true,
            ),
          ),
        )
      ],
    ),
  ),
);
}


@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(
    title: Text('Title'),
    centerTitle: true,
  ),
  body: StreamBuilder(
    stream: Firestore.instance.collection('randomDB').snapshots(),
    builder: (context, snapshot) {
      if (!snapshot.hasData) return const Text('Loading...');
      return ListView.builder(
        itemExtent: 225.0,
        itemCount: snapshot.data.documents.length,
        itemBuilder: (context, index) =>
            _buildListItems(context, snapshot.data.documents[index]),
      );
    },
  ),
}

Когда документ ['summary'] слишком длинный, текст переполняется через виджет карты. В течение этого времени все, что я делаю, это увеличиваю itemExtent в ListView.Builder.

Есть ли способ установить высоту ListView динамически?

8 ответов

ПРОСТОЕ РЕШЕНИЕ

Добавить shrinkWrap: true для вас ListView.builder.

и он будет принимать автоматическую высоту в зависимости от содержимого внутри вашего Card виджет

ListView.builder(
  shrinkWrap: true,
  physics: NeverScrollableScrollPhysics(),
  itemCount: snapshot.data['transactions'].length,
  itemBuilder: (context, i) {
  return transfers(
  snapshot.data['transactions'][i]);
 },
),

Я считаю, что столбец имеет нечто, называемое mainAxisSize свойство

Column(
  mainAxisSize: MainAxisSize.min,
)

MainAxisSize.min будет увеличивать размер столбца до минимального размера дочерних элементов. Напротив него MainAxisSize.max растянется до максимального размера, которого он может достичь.

Но я еще не проверял это. Надеюсь, это поможет

Вы можете использовать мою реализацию

Widget adapter(List<String> strings){
    List<Widget> widgets= List<Widget>();
    for(int i=0;i<strings.length;i++){
      widgets.add(Text(strings[i]));
    }

    Row row=Row(
            children: <Widget>[
              Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children:widgets
              ),
            ],
          );
    return row;
  }

В этом примере отображается список строк

       ListView.builder(
                        padding: EdgeInsets.zero,
                        shrinkWrap: true,
                        itemCount: provider.products.length,
                        itemBuilder: (BuildContext context, int index) {
                          return InkWell(
                            onTap: () => viewProductDetail(provider.products[index]),
                            child: const OrderDetailsWidgets().orderedProducts(
                              title: provider.products[index].itemName ?? '',
                              price: '---',
                              img: provider.products[index].productImage ??
                                  'request-list-image.png',
                              context: context,
                            ),
                          );
                        },
                      ),

добавление нулевого заполнения для listview.builder уменьшило высоту

Создать индивидуальный ListView itemBuilder Пример кода приведен ниже:

 Container(
  child: ListView.builder(
    padding: EdgeInsets.all(5),
    itemCount: snapshot.data.length,
    physics: BouncingScrollPhysics(),
    itemBuilder: (context, index) {
    return generateColum(snapshot.data[index]);
   }),
);

  Widget generateColum(HouseholderModel item) => Card(
  child: InkWell(
    onTap: () {
    },
    child: Stack(
      children: <Widget>[
        Padding(
          padding: const EdgeInsets.only(left: 5.0, top: 5.0, right: 5.0, bottom: 5.0),
          child: ConstrainedBox(
            constraints: BoxConstraints(
              minHeight: 70,
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                CircleAvatar(
                  radius: 25,
                  foregroundColor: Colors.transparent,
                  backgroundColor: appThemeColor.withOpacity(0.5),
                  child: CachedNetworkImage(
                    imageUrl: testImage,
                  )
                ),
                Container(
                  padding: EdgeInsets.fromLTRB(8.0, 5.0, 0.0, 5.0),
                  width: MediaQuery.of(context).size.width * .60,
                  color: Colors.transparent,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(
                        "777 Brockton Avenue",
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                        style: CustomTextStyle.textSubtitle2BlackShades(context),
                      ),
                      Text(
                        'Michael Smith',
                        maxLines: 2,
                        overflow: TextOverflow.ellipsis,
                        style: CustomTextStyle.textSubtitle1blueShades(context),
                      )
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
        Positioned(
          bottom: 0.1,
          right: 0.1,
          child: Container(
            padding: EdgeInsets.all(2),

            decoration: BoxDecoration(
                boxShadow: [BoxShadow(
                  color: Colors.grey,
                  blurRadius: 2.0,
                ),],
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(3.0),
                  bottomRight: Radius.circular(3.0)),
              color: appThemeColor,
            ),
            height: 15,
            width: MediaQuery.of(context).size.width * .20,
            child: Container(
              alignment: Alignment.center,
              child: FittedBox(fit:BoxFit.fitWidth,
                child: Text('Vice-President', style: CustomTextStyle.textSubtitle1(context).copyWith(color: Colors.white),),)

            ),
          ),
        ),
      ],
    ),
  ),
  );

Просто не указывайте itemExtent параметр.

Или просто дать ему null значение, а не 225.0

Таким образом, ребенок получит точную необходимую высоту в ListView

Просто установитеshrinkWrap: true, представление списка автоматически примет необходимую высоту.

Пытаться

      class HomePage extends StatelessWidget {
 Widget _buildListItems(BuildContext context, DocumentSnapshot document) {
  return Center(
   child: Card(
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Flexible(
          ListTile(
          title: Text(document['title']),
          subtitle: Text(document['subtitle']),
        ),
        ),
        Expanded(
          child: Container(
            padding: EdgeInsets.all(20.0),
            child: Text(
              document['summary'],
              softWrap: true,
            ),
          ),
        )
      ],
    ),
  ),
);
}
Другие вопросы по тегам