skip to Main Content

I am trying to create an extension to add space between children of Columns or Rows.
I created two extensions, but I do not know which is proper or good coding practice to create that extension.
Can someone help me with which is the better way and why????

The first one directly applied to the Column/Row widget

Extension Code:

extension SeparatedList<T> on Flex {
  Widget gap(double separatorSize, {Axis axis = Axis.vertical}) {
    var newList = <Widget>[];
    for (var element in children) {
      newList.add(element);
    }
    children.clear();
    for (var i = 0; i < newList.length; i++) {
      if (i == 0) {
        children.add(newList[i]);
      } else {
        children.addAll([
          axis == Axis.horizontal
              ? SizedBox(width: separatorSize)
              : SizedBox(height: separatorSize),
          newList[i],
        ]);
      }
    }
    return this;
  }
}

Use of extension

Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ).gap(40),
      )

Second one applied to List of Column/Row

Extension Code:

extension SeparatedList<T> on List<T> {
  List<Widget> separated(double separatorSize, {Axis axis = Axis.vertical}) {
    final newList = <Widget>[];
    for (var i = 0; i < length; i++) {
      if (i == 0) {
        newList.add(this[i] as Widget);
      } else {
        switch (axis) {
          case Axis.horizontal:
            newList.add(SizedBox(width: separatorSize));
          case Axis.vertical:
            newList.add(SizedBox(height: separatorSize));
        }
        newList.add(this[i] as Widget);
      }
    }
    return newList;
  }
}

Use of extension

Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ].separated(40),
        ),
      )

2

Answers


  1. Both options are suitable for use, but I prefer the second one because it can also be utilized in other widgets. I have an extension with a similar purpose as yours, but it provides the option to show the first and last separater.

    extension ListWidgetExtend<T extends Widget> on List<T> {
      List<Widget> withDivider(Widget divider, {bool showLast = false, bool showFirst = false}) {
        if (isNullOrEmpty()) return [];
    
        List<Widget> rs = [];
        if (showFirst) {
          rs.add(divider);
        }
        forEach((element) {
          rs.add(element);
          rs.add(divider);
        });
        if (!showLast) {
          rs.removeLast();
        }
        return rs;
      }
    }
    
    Login or Signup to reply.
  2. Better way? Well, DON’T use separator extension for Col/Row. As you can see, in your extension, there is a for loop. A for loop with cost Big O(length). So my advice is don’t use a for loop.

    Besides, many UI designs don’t have a fixed gapHeight/gapWidth so I barely use it.

    Anyway, those 2 above are the same, you can choose whatever you want.

    Edit: Read more about Big O Notation – time complexity.

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