0 purchases
widget modifier
A collection of built-in flutter widget modifiers, which flatten the widget tree and make it easier to read.
Credit: Original idea and the widget_modifier base code is a modified version of nested widget by @remi_rousselet
Problem #
AspectRatio(
aspectRatio: 16 / 8,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: DecoratedBox(
decoration: BoxDecoration(
color: const Color(0xFFe1e4e3),
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(),
),
),
)
copied to clipboard
This is a typical flutter widget. With four nested widgets, the code is pretty hard to read. Your eyes need to skim to Padding, AspectRatio, DecoratedBox, and Padding to reach out to the actual child widget. This process is unnecessary and consumes your brain's power to do.
Of course, no one in the real world does this. Instead, we use a big friendly (or maybe not) guy - Container. The previous widget becomes this.
AspectRatio(
aspectRatio: 16 / 8,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: const Color(0xFFe1e4e3),
borderRadius: BorderRadius.circular(20),
),
padding: const EdgeInsets.all(20),
child: Row(),
),
)
copied to clipboard
But why do we still have AspectRatio widget? Because Container doesn't have aspectRatio field. It means Container is not flexible to provide all kinds of configurations you need.
To fix this, widget_modifier introduces a new set of APIs to "flatten" your widget.
Usage #
Widget modifier have two API styles: declarative and cascading
Declarative #
Declarative modifier version of the above example widget
Modifier(
modifiers: [
AspectRatioModifier(
aspectRatio: 16 / 8,
),
PaddingModifier(
padding: const EdgeInsets.symmetric(horizontal: 20),
),
DecoratedBoxModifier(
decoration: BoxDecoration(
color: const Color(0xFFe1e4e3),
borderRadius: BorderRadius.circular(20),
),
),
PaddingModifier(
padding: const EdgeInsets.all(20),
)
],
child: Row(),
),
copied to clipboard
modifiers: a List<SingleChildModifier> basically the wrapper for a typical Widget which has one child
child: child of Modifier
The declarative modifier will apply from the bottom element to the top element of the modifiers list.
Pros & Cons
Pros:
Easy to detect where the root child widget
Nice code format
Work well with editor code folding
Cons:
Counter-intuitive at first
Cascading #
Cascading modifier version of the above example widget
Row()
.modified()
.wrapWith(PaddingModifier(
padding: const EdgeInsets.all(20),
))
.wrapWith(DecoratedBoxModifier(
decoration: BoxDecoration(
color: const Color(0xFFe1e4e3),
borderRadius: BorderRadius.circular(20),
),
))
.wrapWith(PaddingModifier(
padding: const EdgeInsets.symmetric(horizontal: 20),
))
.wrapWith(AspectRatioModifier(
aspectRatio: 16 / 8,
))
copied to clipboard
modified(): extenstion turn your widget to Modifier
wrapWith(): insert SingleChildModifier to the beginning of the modifiers list
wrapWithAll(): insert List<SingleChildModifier> to the beginning of the modifiers list
The cascading modifier will apply from the top wrapWith/wrapWithAll element to the bottom.
Pros & Cons
Pros:
Easy to detect where the root child widget
Intuitive to read
Cons:
Code format is sometimes ugly
Custom modifier #
If you want to make a custom modifier check out SingleChildStatelessModifier/SingleChildStatefulModifier equivalents version StatelessWidget/StatefulWidget
Caution
⚠️ You need to override buildWithChild instead of build method
⚠️ buildWithChild is like build but has another child parameter which is the widget Modifier given to SingleChildModifier
⚠️ modifierKey is the key of the actual widget inside the modifier
SingleChildStatelessModifier #
class ConstrainedBoxModifier extends SingleChildStatelessModifier {
ConstrainedBoxModifier({
Key? key,
Widget? child,
super.modifierKey,
required this.constraints,
}) : assert(constraints.debugAssertIsValid()),
super(key: key, child: child);
final BoxConstraints constraints;
@override
Widget buildWithChild(BuildContext context, Widget? child) {
return ConstrainedBox(
key: modifierKey,
constraints: constraints,
child: child,
);
}
}
copied to clipboard
SingleChildStatefulModifier #
You need to implements SingleChildStateMixin mixin in State class of SingleChildStatefulModifier
class StatefulBuilderModifier extends SingleChildStatefulModifier {
const StatefulBuilderModifier({
super.key,
super.modifierKey,
required this.builder,
});
final SingleChildStatefulWidgetBuilder builder;
@override
State<StatefulWidget> createState() => _StatefulBuilderModifierState();
}
class _StatefulBuilderModifierState extends State<StatefulBuilderModifier>
with SingleChildStateMixin<StatefulBuilderModifier> {
@override
Widget buildWithChild(BuildContext context, Widget child) {
return widget.builder(context, setState, child);
}
}
copied to clipboard
Editor support #
You can easily convert existing widget to Modifier with my extension. See more at:
vscode
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.