Search code examples
flutterlistviewdartrowhybrid-mobile-app

Flutter ListView with Row Property of space between


Looking for Flutter Listview with horizontal scroll and Row Property of space between(automatically adjust items with equal spaces) if the item count is less(can fit in on the screen) and slide if the item count is more

enter image description here


Solution

  • Solved by creating keys for each element in the List, then calculating it size in runtime.

    If the size of all the elements together is more than the Screen Width, We can have a Row, otherwise, we need to use ListView

    import 'package:flutter/material.dart';
    import 'package:flutter/scheduler.dart';
    
    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      double elementsWidth;
      List paymentMethodsList;
    
      @override
      void initState() {
        paymentMethodsList = [
          {
            'paymentName': 'UPI Transfer',
            "key": GlobalKey(),
          },
          {
            'paymentName': 'NEFT Transfer',
            "key": GlobalKey(),
          },
          {
            'paymentName': 'IMPS Transfer',
            "key": GlobalKey(),
          },
          {
            'paymentName': 'RTGS Transfer',
            "key": GlobalKey(),
          },
          {
            'paymentName': 'UPI Collect',
            "key": GlobalKey(),
          },
        ];
        super.initState();
      }
    
      void postFrameCallback(_) {
        double widthOfElements = 0;
        int numberOfElementsParsed = 0;
        for (int i = 0; i < paymentMethodsList.length; i++) {
          var context = paymentMethodsList[i]['key'].currentContext;
          if (context == null) return;
          numberOfElementsParsed++;
          widthOfElements += context.size.width;
        }
        if (numberOfElementsParsed == paymentMethodsList.length) {
          setState(() {
            elementsWidth = 100 + widthOfElements;
            print(elementsWidth);
          });
        }
        // if (oldSize == newSize) return;
    
        // oldSize = newSize;
        // widget.onChange(newSize);
      }
    
      @override
      Widget build(BuildContext context) {
        SchedulerBinding.instance.addPostFrameCallback(postFrameCallback);
        return Scaffold(
          backgroundColor: Colors.black,
          // appBar: buildAppBar(),
          body: buildPage(),
        );
      }
    
      buildPage() => Column(
            children: [
              SizedBox(
                height: 25,
              ),
              buildPaymentListWidget(),
              // SizedBox(
              //   height: 20,
              // ),
            ],
          );
    
      Container buildPaymentListWidget() {
        return Container(
          height: 90,
          padding: EdgeInsets.only(left: 20, right: 20),
          child: elementsWidth != null &&
                  elementsWidth < MediaQuery.of(context).size.width
              ? Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    for (var i = 0; i < paymentMethodsList.length; i++)
                      buildPaymentItemWidget(i)
                  ],
                )
              : ListView.separated(
                  shrinkWrap: false,
                  scrollDirection: Axis.horizontal,
                  separatorBuilder: (context, index) => SizedBox(
                    width: 15,
                  ),
                  itemBuilder: (context, index) {
                    return buildPaymentItemWidget(index);
                  },
                  itemCount: paymentMethodsList.length,
                ),
        );
      }
    
      Container buildPaymentItemWidget(int index) {
        return Container(
          key: paymentMethodsList[index]['key'],
          child: Text(
            paymentMethodsList[index]['paymentName'],
            textAlign: TextAlign.center,
            style: TextStyle(
                fontSize: 12, fontWeight: FontWeight.w400, color: Colors.white),
          ),
        );
      }
    }