skip to Main Content

How can i create a packed list of items with horizontal scrolling and fixed rows in flutter?. Wrap makes each item a fixed weightI want to achive the look of the attached image

2

Answers


  1. If you only need the rows to scroll together (and manually decide which row each chip goes into), all you need is warp the rows in a column then put them in a horizontal scrollable.

    
    class ChipGrid extends StatelessWidget {
      const ChipGrid({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          scrollDirection: Axis.horizontal,
          children: [
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    for (var i = 0; i < 10; i++)
                      Chip(label: Text('Item Number $i')),
                  ],
                ),
                Row(
                  children: [
                    for (var i = 10; i < 20; i++)
                      Chip(label: Text('Item Number $i')),
                  ],
                ),
                Row(
                  children: [
                    for (var i = 20; i < 30; i++)
                      Chip(label: Text('Item Number(Row 3): $i')),
                  ],
                ),
              ],
            )
          ],
        );
      }
    }
    
    Login or Signup to reply.
  2. You can use the Column to create separated line of chips and fill it with calculated total chips / line count.

    Workaround code below to demonstrate the result:

    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      static const line = 3;
    
      final chips = [
        ChipsWidget(label: 'Physics', count: 1950),
        ChipsWidget(label: 'Meat', count: 1950),
        ChipsWidget(label: 'Application', count: 1950),
        ChipsWidget(label: 'Library', count: 1950),
        ChipsWidget(label: 'Reception', count: 1950),
        ChipsWidget(label: 'Wedding', count: 1950),
        ChipsWidget(label: 'Food', count: 1950),
        ChipsWidget(label: 'Emphasis', count: 1950),
        ChipsWidget(label: 'Disease', count: 1950),
        ChipsWidget(label: 'Presence', count: 1950),
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.lightBlueAccent.shade100,
          body: ListView(
            scrollDirection: Axis.horizontal,
            padding: EdgeInsets.all(10),
            children: [
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: List.generate(
                  line,
                  (id) => Container(
                    padding: EdgeInsets.only(bottom: 5),
                    height: 40,
                    child: ListView.separated(
                      scrollDirection: Axis.horizontal,
                      shrinkWrap: true,
                      separatorBuilder: (c, i) => SizedBox(width: 5),
                      itemCount: (chips.length / line).ceil(),
                      itemBuilder: (c, i) => chips.elementAtOrNull(
                        ((chips.length / line).ceil() * (id)) + i,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    class ChipsWidget extends StatelessWidget {
      const ChipsWidget({
        super.key,
        required this.label,
        required this.count,
      });
    
      final String label;
      final int count;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
          decoration: ShapeDecoration(
            shape: StadiumBorder(),
            color: Colors.white,
          ),
          child: Row(mainAxisSize: MainAxisSize.min, children: [
            Text(label),
            SizedBox(width: 5),
            Text(count.toString()),
          ]),
        );
      }
    }
    

    And this is the result:

    demo

    Hopefully it can solve your problem, Thanks 😉

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search