shyndman / flutter_layout_grid

A grid-based layout system for Flutter, inspired by CSS Grid Layout
MIT License
441 stars 43 forks source link

Incorrect Layout when nesting two `LayoutGrid`s inside each other #102

Open FrankenApps opened 1 month ago

FrankenApps commented 1 month ago

First of all thanks for this great and flexible Grid widget.

Unfortunately I've discovered a bug when nesting two Grids inside each other. I've condensed the problem into the sample below:

import 'package:flutter/material.dart';
import 'package:flutter_layout_grid/flutter_layout_grid.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Incorrect Grid',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

// Exchange the commented lines below to see the difference.
const columnSizes = [IntrinsicContentTrackSize()]; // Does not work.
//const columnSizes = [FlexibleTrackSize(1)]; // This works as expected.

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  static final _dummyContent = <Widget>[
    GridPlacement(
        columnStart: 0,
        rowStart: 0,
        child: Container(
            color: Colors.blue, child: const Text('Row 0 | Column 0'))),
    GridPlacement(
        columnStart: 0,
        rowStart: 1,
        child: Container(
            color: Colors.red, child: const Text('Row 1 | Column 0'))),
    GridPlacement(
        columnStart: 1,
        rowStart: 0,
        child: Container(
            color: Colors.purple, child: const Text('Row 0 | Column 1'))),
    GridPlacement(
        columnStart: 1,
        rowStart: 1,
        child: Container(
            color: Colors.orange, child: const Text('Row 1 | Column 1'))),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: const Text('Incorrect Grid'),
        ),
        body: SingleChildScrollView(
          child: LayoutGrid(
            columnSizes: columnSizes,
            rowSizes: const [IntrinsicContentTrackSize()],
            children: [
              GridPlacement(
                  columnStart: 0,
                  rowStart: 0,
                  child: LayoutGrid(
                    columnSizes: const [
                      FlexibleTrackSize(0.5),
                      FlexibleTrackSize(0.5)
                    ],
                    rowSizes: const [
                      IntrinsicContentTrackSize(),
                      IntrinsicContentTrackSize()
                    ],
                    children: _dummyContent,
                  ))
            ],
          ),
        ));
  }
}

This sample unfortunately produces this output: Screenshot_1727802534

While I would have expected it to produce the output below (which can be achieved by changing the column size of the parent grid to FlexibleTrackSize(1) as can be seen in the comment of the provided sample code): Screenshot_1727802501 Side note: It seems very strange to me that changing the columnSizes of the parent grid does have an effect on the rowSizes of the child grid.

I think I've tracked this down to _itemMaxIntrinsicSizeOnAxis incorrectly being supplied with 0 as crossAxisSize by maxIntrinsicSize of IntrinsicContentTrackSize, which itself uses crossAxisSizeForItem to compute the size, but I am not sure how to proceed from there, in order to come up with a fix.