oldie sites
oldie sites

Reputation: 63

How to make parent ListView box size the same as it's largest child in a nested ListView?

For the last couple of days I have been trying to make this work without any luck.

I have two ListViews, one inside the other (nested). I want the items in the parent ListView to have the same size as its largest ListView child.

Is this possible? If so how?

Please let me know if you need any more information.

Upvotes: 1

Views: 294

Answers (1)

amir-msh
amir-msh

Reputation: 1452

Think out of the box!
In some cases, you should write your own customized widget.

I wrote a widget that can help you fix this problem :

class CustomListView extends StatelessWidget {
  final Widget Function(BuildContext, int) sepratorBuilder;
  final Widget Function(BuildContext, int) itemBuilder;
  final int itemCount;
  final Axis scrollDirection;
  final List<Widget> children;
  final EdgeInsetsGeometry padding;

  CustomListView({
    @required this.children,
    this.padding = const EdgeInsets.all(0),
    this.scrollDirection = Axis.vertical,
    // You can add any other property that you want ...
  })  : assert(children != null),
        assert(padding != null),
        assert(scrollDirection != null),
        itemBuilder = null,
        itemCount = null,
        sepratorBuilder = null;

  CustomListView.builder({
    @required this.itemBuilder,
    @required this.itemCount,
    this.padding = const EdgeInsets.all(0),
    this.scrollDirection = Axis.vertical,
    // You can add any other property that you want ...
  })  : assert(itemBuilder != null),
        assert(itemCount != null && itemCount >= 0),
        assert(padding != null),
        assert(scrollDirection != null),
        children = List.generate(
          itemCount,
          (index) => Builder(builder: (context) => itemBuilder(context, index)),
        ),
        sepratorBuilder = null;

  CustomListView.seprated({
    @required this.itemBuilder,
    @required this.itemCount,
    @required this.sepratorBuilder,
    this.padding = const EdgeInsets.all(0),
    this.scrollDirection = Axis.vertical,
    // You can add any other property that you want ...
  })  : assert(itemBuilder != null),
        assert(itemCount != null && itemCount >= 0),
        assert(padding != null),
        assert(scrollDirection != null),
        assert(sepratorBuilder != null),
        children = List.generate(
          itemCount,
          (index) => Builder(
            builder: (context) => Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                itemBuilder(context, index),
                if (index < itemCount - 1) sepratorBuilder(context, index),
              ],
            ),
          ),
        );

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      scrollDirection: scrollDirection,
      child: Padding(
        padding: padding,
        child: scrollDirection == Axis.vertical
            ? Column(
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: children,
              )
            : Row(
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: children,
              ),
      ),
    );
  }
}

And you can use it like this :

class HomePage extends StatelessWidget {
  Widget itemBuilder(BuildContext context, int index) => Row(
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.min,
        children: List.generate(
          3,
          (index) => Container(
            margin: const EdgeInsets.all(5),
            width: (Random().nextInt(50) + 50).toDouble(),
            height: 50,
            decoration: BoxDecoration(
              color: Color(
                (0xFFFFFFFF * Random().nextDouble()).floor() | 0xFF0000FF,
              ),
              borderRadius: const BorderRadius.all(Radius.circular(12.5)),
            ),
          ),
        ),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.amber,
      body: Center(
        child: CustomListView.builder(
          padding: const EdgeInsets.only(top: 30, bottom: 30),
          itemCount: 20,
          itemBuilder: itemBuilder,
        ),
      ),
    );
  }
}

This is the output :

Output


If you enable debug paint you can see the width of the CustomListView is the exact same as its widest child :

Output

Upvotes: 4

Related Questions