Flutter ListView.builder() widget's cross Axis is taking up the entire Screen height

1,010

This question is similar to this: Flutter: Minimum height on horizontal list view

After digging around a bit, I've realized that a ListView may not be the widget you are looking for.

Prior to this, I showed that the only way to control the height of the ListView was through a fixed setting of height because that is what a ListView is designed to do - display a list of items that is pre-formatted.

If you want to have the same functionality where the children set the height instead, meaning the widget wraps only the content, then I would suggest a SingleChildScrollView with a Row (note: Make sure to set the scrollDirection: Axis.horizontal)

Like this: Output

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: Container(
              // height: 100, // no need to specify here
              color: Colors.white,
              child: SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Row(
                  children: <Widget>[
                    Container(
                      height: 300,
                      width: 300,
                      color: Colors.amber[600],
                      child: const Center(child: Text('Entry A')),
                    ),
                    Container(
                      height: 100,
                      color: Colors.amber[500],
                      child: const Center(child: Text('Entry B')),
                    ),
                    Container(
                      height: 50,
                      width: 100,
                      color: Colors.amber[100],
                      child: const Center(child: Text('Entry C')),
                    ),
                    Container(
                      height: 300,
                      width: 300,
                      color: Colors.amber[600],
                      child: const Center(child: Text('Entry A')),
                    ),
                    Container(
                      height: 100,
                      color: Colors.amber[500],
                      child: const Center(child: Text('Entry B')),
                    ),
                    Container(
                      height: 50,
                      width: 100,
                      color: Colors.amber[100],
                      child: const Center(child: Text('Entry C')),
                    ),
                    Container(
                      height: 300,
                      width: 300,
                      color: Colors.amber[600],
                      child: const Center(child: Text('Entry A')),
                    ),
                    Container(
                      height: 100,
                      color: Colors.amber[500],
                      child: const Center(child: Text('Entry B')),
                    ),
                    Container(
                      height: 50,
                      width: 100,
                      color: Colors.amber[100],
                      child: const Center(child: Text('Entry C')),
                    ),
                    Container(
                      height: 300,
                      width: 300,
                      color: Colors.amber[600],
                      child: const Center(child: Text('Entry A')),
                    ),
                    Container(
                      height: 100,
                      color: Colors.amber[500],
                      child: const Center(child: Text('Entry B')),
                    ),
                    Container(
                      height: 50,
                      width: 100,
                      color: Colors.amber[100],
                      child: const Center(child: Text('Entry C')),
                    ),
                    Container(
                      height: 300,
                      width: 300,
                      color: Colors.amber[600],
                      child: const Center(child: Text('Entry A')),
                    ),
                    Container(
                      height: 100,
                      color: Colors.amber[500],
                      child: const Center(child: Text('Entry B')),
                    ),
                    Container(
                      height: 50,
                      width: 100,
                      color: Colors.amber[100],
                      child: const Center(child: Text('Entry C')),
                    ),
                  ],
                ),
              )),
        ),
      ),
    );
  }
}

+++++++Added after OP comment+++++++

If you want to use a builder for a dynamic list, you can always define your own too!

output

import 'dart:math';

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  var _randHeight = Random();

  List<int> someList = [
    1,
    2,
    3,
    4,
    5,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20
  ];

  var randHeight = Random();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: Container(
              color: Colors.white,
              child: SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: _createChildren(),
                ),
              )),
        ),
      ),
    );
  }

  List<Widget> _createChildren() {
    return List<Widget>.generate(someList.length, (int index) {
      return Container(
        color: Colors.red,
        width: 100,
        height: _randHeight.nextInt(300).toDouble(),
        child: Text(someList[index].toString(),
            style: TextStyle(color: Colors.black)),
      );
    });
  }
}
Share:
1,010
Sasank Sunkavalli
Author by

Sasank Sunkavalli

Mobile Developer

Updated on November 28, 2022

Comments

  • Sasank Sunkavalli
    Sasank Sunkavalli over 1 year

    I am using ListView.builder(scrollDirection: Horizontal) widget inside a Container in Flutter. The main Axis of the ListView is taking up the entire screen width which is expected. I want the ListView's crossAxis(vertical direction) to take up the ListView's Item height (only wrapping the content), but it is taking up the entire screen height.

    I have created the DartPard to explain the Issue. I want the ListView to take up the Item height and not the entire screen height. Dart Pad Link : DartPard which shows the issue I am facing

    import 'package:flutter/material.dart';
    
    final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
              theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
              debugShowCheckedModeBanner: false,
              home: Scaffold(
                  body: SafeArea(
                  child: Container(
                  color: Colors.white,
                  child: ListView.builder(
                      itemCount: 10,
                      scrollDirection: Axis.horizontal,
                  itemBuilder: (context, index) {
                      return Container(
                               color: Colors.red,
                               child: Text(
                                 'Item $index', 
                                 style: TextStyle(color: Colors.black),
                      ),  
                  );
                },
              ),
             ),
            ),
           ),
          );
         }
        }
    

    Few workarounds which will work :

    1. Using Row or Wrap instead of ListView.
    2. Giving a Fixed height to the ListView.

    I know the above listed approaches will work. But I want to achieve this using a ListView only.

  • Sasank Sunkavalli
    Sasank Sunkavalli over 3 years
    shrinkWrap will shrink the ListView along the main axis. I have asked for the Cross Axis.
  • Sasank Sunkavalli
    Sasank Sunkavalli over 3 years
    there is no way other than using a fixed height for the ListView ?
  • Gene
    Gene over 3 years
    No, I believe ListViews require the same CrossAxis size for each object. I updated the answer with what I believe you are looking for
  • Sasank Sunkavalli
    Sasank Sunkavalli over 3 years
    Yes Using a Row will solve my Issue. But I need to use a ListView.builder() since the list is dynamic and I even want to paginate the list(Items more than 1000 items)
  • Gene
    Gene over 3 years
    Perhaps you can define your own builder? Check updated answer