Flutter. Simplifying Widget Layout with Dart Extensions

image



In Dart 2.7, we were introduced to extensions that allow developers to add new functionality to existing types. Extensions can be a great helper not only when we write business logic, but also when we have other tasks! An example of such a task is working with widgets.



Based on my experience in iOS development, inspired by ViewModifierSwiftUI, I wanted to figure out how to use Dart extensions in a similar way to reduce the visual clutter that results from a large nesting of the widget tree.



Let's take an example!



Option with nested widgets



Below is a MyWidgetwidget with text inside Padding(from the standard example with dartpad.dev ).



class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return
      Padding(
        padding: const EdgeInsets.all(16),
        child: Text('Hello, World!', style: Theme.of(context).textTheme.headline4)
      );
  }
}


Now let's see how we can do the same with Dart extensions.



Option with extensions



We create an extension for the class Widgetwith the method padding. When this method is called, the object will be wrapped in Padding:



extension WidgetModifier on Widget {
  Widget padding([EdgeInsetsGeometry value = const EdgeInsets.all(16)]) {
    return Padding(
      padding: value,
      child: this,
    );
  }
}


With the new extension, we can update MyWidgetas follows:



class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('Hello, World!', style: Theme.of(context).textTheme.headline4)
            .padding();
  }
}


, , ! , , .



:



extension WidgetModifier on Widget {

  // ...

  Widget background(Color color) { // 
    return DecoratedBox(
      decoration: BoxDecoration(
        color: color,
      ),
      child: this,
    );
  }

  Widget cornerRadius(BorderRadiusGeometry radius) { //  
    return ClipRRect(
      borderRadius: radius,
      child: this,
    );
  }

  Widget align([AlignmentGeometry alignment = Alignment.center]) { // 
    return Align(
      alignment: alignment,
      child: this,
    );
  }
}


class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('Hello, World!', style: Theme.of(context).textTheme.headline4)
            .padding()
            .background(Colors.lightBlue)
            .cornerRadius(BorderRadius.all(Radius.circular(8.0)))
            .padding(EdgeInsets.symmetric(horizontal: 8, vertical: 16))
            .background(Colors.purple);
  }
}




dartpad.dev

? , ! , , .





In this article, we considered an alternative approach to forming a tree of widgets in a Flutter project, using a concept similar to that ViewModifierfrom SwiftUI. With this approach, we can simplify the widget trees by reducing their nesting. And I have demonstrated only a few examples of such extensions, but by the same principle, you can create many new ones for other cases where they will be just as useful.



Thanks for your attention! Hope you find this post helpful. If you have any questions or comments about this material, feel free to contact me on Twitter !



Until next time!




All Articles