Enhancing Flutter Development with Custom Extensions: A Practical Guide

Maximize your Flutter development efficiency with these custom widget and utility extensions. Streamline your code and boost productivity!

Gautam
4 min readJun 11, 2024

Flutter is a powerful framework for building cross-platform applications, but sometimes, you need a bit more flexibility and efficiency in your development process. Custom extensions can help you streamline repetitive tasks, improve code readability, and make your widgets more versatile. In this blog, we’ll explore some practical Flutter extensions and demonstrate how to use them to enhance your Flutter development experience.

Custom Widget Extensions

Custom widget extensions allow you to add reusable functionalities to your widgets, making your code cleaner and more readable. Below are some useful extensions that you can integrate into your Flutter projects.

Wrapping Widgets with Align

Aligning widgets is a common task in Flutter development. This extension simplifies the process by allowing you to wrap any widget with an Align widget.

extension CustomWidget on Widget {
/// To wrap the widget with the (Align) widget.
Widget align({AlignmentGeometry? alignment}) {
return Align(alignment: alignment ?? Alignment.center, child: this);
}
}

Adding Padding to Widgets

Adding padding to widgets is another frequent task. These extensions make it easy to add different types of padding to your widgets.

extension CustomWidget on Widget {
/// Returns custom padding for all sides.
Widget paddingAll(double padding) {
return Padding(padding: EdgeInsets.all(padding), child: this);
}

/// Returns custom symmetric padding from the horizontal side.
Widget paddingHorizontal(double padding) {
return Padding(padding: EdgeInsets.symmetric(horizontal: padding), child: this);
}

/// Returns custom symmetric padding from the vertical side.
Widget paddingVertical(double padding) {
return Padding(padding: EdgeInsets.symmetric(vertical: padding), child: this);
}

/// Returns custom symmetric padding from each side.
Widget paddingSymmetric({required double vertical, required double horizontal}) {
return Padding(
padding: EdgeInsets.symmetric(vertical: vertical, horizontal: horizontal),
child: this,
);
}

/// Returns custom padding from each side.
Widget paddingOnly({
double top = 0.0,
double left = 0.0,
double bottom = 0.0,
double right = 0.0,
}) {
return Padding(
padding: EdgeInsets.fromLTRB(left, top, right, bottom),
child: this,
);
}
}

Utility Extensions

Utility extensions can enhance basic types like int and Widget?, adding useful methods that save you from writing repetitive code.

Extensions for int

These extensions add various functionalities to the int type, making it more versatile.

extension IntExtensions on int {
int validate({int value = 0}) {
return this;
}

Widget get sizedBoxHeight => SizedBox(height: toDouble());

Widget get sizedWidth => SizedBox(width: toDouble());

Duration get seconds => Duration(seconds: validate());

Duration get milliseconds => Duration(milliseconds: validate());

Duration get days => Duration(days: validate());

bool isBetween(num first, num second) {
return validate() >= first && validate() <= second;
}

Size get size => Size(toDouble(), toDouble());

String get nthDaySuffix {
if (this < 1 || this > 31) {
throw Exception("Invalid day of month");
}
if (this >= 11 && this <= 13) {
return "${this}th";
}
switch (this % 10) {
case 1:
return "${this}st";
case 2:
return "${this}nd";
case 3:
return "${this}rd";
default:
return "${this}th";
}
}
}

Extensions for Widget?

These extensions provide additional functionalities for nullable widgets, helping to handle various layout and visibility scenarios.

extension WidgetExtension on Widget? {
SizedBox withSize({double width = 0.0, double height = 0.0}) {
return SizedBox(height: height, width: width, child: this);
}

SizedBox withWidth(double width) => SizedBox(width: width, child: this);

SizedBox withHeight(double height) => SizedBox(height: height, child: this);

Widget visible(bool visible, Widget? defaultWidget) {
return visible ? this! : (defaultWidget ?? const SizedBox.shrink());
}

Widget opacity({
required double opacity,
int durationInSecond = 1,
Duration? duration,
}) {
return AnimatedOpacity(
opacity: opacity,
duration: duration ?? Duration(milliseconds: (durationInSecond * 1000)),
child: this,
);
}

Widget rotate({
required double angle,
bool transformHitTests = true,
Offset? origin,
}) {
return Transform.rotate(
angle: angle,
transformHitTests: transformHitTests,
origin: origin,
child: this,
);
}

Widget scale({
required double scale,
Offset? origin,
AlignmentGeometry? alignment,
bool transformHitTests = true,
}) {
return Transform.scale(
scale: scale,
origin: origin,
alignment: alignment,
transformHitTests: transformHitTests,
child: this,
);
}

Widget center({double? heightFactor, double? widthFactor}) {
return Center(
heightFactor: heightFactor,
widthFactor: widthFactor,
child: this,
);
}

Widget onTap(
Function? function, {
BorderRadius? borderRadius,
Color? splashColor,
Color? hoverColor,
Color? highlightColor,
}) {
return InkWell(
onTap: function as void Function()?,
borderRadius: borderRadius,
splashColor: splashColor,
hoverColor: hoverColor,
highlightColor: highlightColor,
child: this,
);
}
}

Practical Use Cases

Let’s look at how these extensions can be used in real-world Flutter applications to improve code readability and maintainability.

Aligning and Padding Widgets

Instead of wrapping widgets with Align and Padding manually, you can use the extensions for a cleaner approach:

Widget build(BuildContext context) {
return Container(
child: Text('Hello, World!')
.align(alignment: Alignment.center)
.paddingAll(16.0),
);
}

Creating Sized Boxes

Creating sized boxes becomes simpler with the int extensions:

Widget build(BuildContext context) {
return Column(
children: [
10.sizedBoxHeight,
Text('Hello, World!'),
20.sizedWidth,
Text('Welcome to Flutter'),
],
);
}

Handling Visibility and Opacity

Managing widget visibility and opacity transitions can be done more elegantly:

Widget build(BuildContext context) {
return Column(
children: [
Text('Visible Widget').visible(true, null),
Text('Fading Widget').opacity(opacity: 0.5, durationInSecond: 2),
],
);
}

Conclusion

Custom extensions in Flutter offer a powerful way to streamline your development process, reduce boilerplate code, and enhance readability. By incorporating these extensions into your projects, you can improve your productivity and create more maintainable codebases. Try out these extensions in your next Flutter project and experience the benefits firsthand.

If you enjoyed this post and want to support my work, consider buying me a coffee. Your contribution helps keep the code flowing and the projects coming. Buy me a coffee and join me on this journey! ☕🚀

--

--

Gautam
Gautam

Responses (1)