0

I'm trying to create a gridview which works like Stagarredgridview.count but without using any package, i've created it using CustomMultichildLayout but i can't make it scrollable. I know i can use any scrollable like singlechildscrollview or listview for this.

The main problem is infinite height which i can't seem to resolve, i've tried layout builder,expanded and flexible widgets for constraints even boxconstraints from Container but can't resolve infinite height.

Here's the code


class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Column(
        children: [
          Expanded(
            child: OrganicGrid(count: 50),
          ),
        ],
      ),
    );
  }
}

class OrganicGrid extends StatelessWidget {
  final int count;
  const OrganicGrid({
    required this.count,
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return CustomGrid(
      children: List.generate(count, (index) => ContainerWidget(id: index + 1)),
    );
  }
}

class ContainerWidget extends StatelessWidget {
  final int id;
  const ContainerWidget({
    required this.id,
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Container(
        height: 50,
        decoration: const BoxDecoration(
          color: Colors.green,
          // border: Border.all(color: Colors.red, width: 2),
        ),
        child: Center(
            child: Text(
          "Text $id",
          style: TextStyle(color: Colors.white),
        )),
      ),
    );
  }
}

class CustomGrid extends StatelessWidget {
  final List<Widget> children;
  const CustomGrid({required this.children, super.key});

  @override
  Widget build(BuildContext context) {
    List<Widget> rows = [];

    bool oddExist = children.length % 2 != 0;

    if (oddExist) {
      rows.add(LayoutId(id: 0, child: children[0]));
    }

    if (oddExist) {
      for (int i = 1; i < children.length; i++) {
        rows.add(LayoutId(id: i, child: children[i]));
      }
    } else {
      for (int i = 1; i <= children.length; i++) {
        rows.add(LayoutId(id: i, child: children[i - 1]));
      }
    }

    return CustomMultiChildLayout(
      key: key,
      delegate: CustomGridDelegate(numRows: rows.length, oddExist: oddExist),
      children: rows,
    );
  }
}

class CustomGridDelegate extends MultiChildLayoutDelegate {
  final int numRows;
  final bool oddExist;

  CustomGridDelegate({required this.numRows, required this.oddExist});

  @override
  void performLayout(Size size) {
    const double padding = 8;
    double width = size.width - padding * 3;
    double childHeight = 60;
    double dy = 0;
    double dx = padding;

  void childLayout(int i) {
      positionChild(i, Offset(dx, dy));
      layoutChild(
        i,
        BoxConstraints(minWidth: width / 2, maxWidth: width / 2),
      );
      if (i % 2 == 0) {
        dy += childHeight;
        dx = padding;
      } else {
        dx = width / 2;
        dx += padding * 2;
      }
    }

    void zerothChildLayout(int i) {
      positionChild(i, Offset(dx, dy));
      layoutChild(
        0,
        BoxConstraints(minWidth: width + padding),
      );
      dy += childHeight;
    }

    if (oddExist) {
      zerothChildLayout(0);
      for (int i = 1; i < numRows; i++) {
        childLayout(i);
      }
    } else {
      for (int i = 1; i <= numRows; i++) {
        childLayout(i);
      }
    }
  }

  @override
  bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => false;
}

I've tried layoutbuilder,boxconstraints,expanded,flexible and similar widets without success, the only way it work is by wraping with fixed size container but that is not dynamic.

Any help would be appreciated, you can directly try this code by pasting.

Cloud
  • 1
  • 2
  • Have you already taken a look at GridView.builder? – Sebb Feb 14 '23 at 09:28
  • I have it is not possible with gridview.builder, there is a package which does exactly this called staggared gridview but I'm trying to do it without using any package. – Cloud Feb 15 '23 at 04:00

0 Answers0