Decorators
Decorators in Mix extend functionality by defining the widget composition tree structure, providing support for core widgets, external widgets, and third-party widgets without compromising the simplicity of core Mix.
Understanding the Mechanics
Take the scale
attribute, for instance. The Container widget doesn't inherently possess the ability to scale. But, by employing a Transform widget as a decorator, we can introduce this effect.
Transform.scale(
scale: 0.5,
child: Container(
child: const Text("Half sized box"),
),
)
Important Note: Decorators are a special kind of attribute that can't be inherited for any child widgets.
Creating a decorator
We can achieve the same effect by creating a custom **WidgetDecorator**
.
Creating a decorator is like creating a **StatelessWidget**
. Extend **WidgetDecorator**
. Define the properties you want to modify and the widget you want to decorate.
class ScaleDecorator extends WidgetDecorator<ScaleDecorator> {
final double scale;
const ScaleDecorator(this.scale, {super.key});
@override
ScaleDecorator lerp(ScaleDecorator? other, double t) {
return ScaleDecorator(lerpDouble(scale, other?.scale, t) ?? scale);
}
@override
get props => [scale];
@override
Widget build(mix, child) {
return Transform.scale(
key: key,
scale: scale,
child: child,
);
}
}
Crafting a decorator utility
To simplify decorator usage, you can design a utility function that automatically creates the decorator for you.
ScaleDecorator scale(double scale, {Key? key}) => ScaleDecorator(scale, key: key);
Using a decorator
final style = Style(
scale(0.5),
);
Box(
style: style,
child: const Text('Half sized box'),
);
Built-in decorators
Mix comes with a set of built-in decorators that can be used out of the box.
Scale Decorator
Decorates a Box
with a Transform.scale
widget
final style = Style(
scale(0.5),
);
// Equivalent to
Transform.scale(
scale: 0.5,
child: Box(
child: const Text('Half sized box'),
),
);
Opacity
Decorates a Box
with an Opacity
widget
final style = Style(
opacity(0.5),
);
// Equivalent to
Opacity(
opacity: 0.5,
child: Box(
child: const Text('Half transparent box'),
),
);
Rotate
Decorates a Box
with a Transform.rotate
widget. The parameter is quarter turns.
final style = Style(
rotate(1),
);
// Equivalent to
RotatedBox(
quarterTurns: 1,
child: Box(
child: const Text('Rotated box'),
),
);
Helper methods
rotate(1)
: 90 degreesrotate.d90()
: 90 degreesrotate(2)
: 180 degreesrotate.d180()
: 180 degreesrotate(3)
: 270 degreesrotate.d270()
: 270 degrees
Aspect Ratio
Decorates a Box
with an AspectRatio
widget
final style = Style(
aspectRatio(6/9),
);
// Equivalent to
AspectRatio(
aspectRatio: 6/9,
child: Box(
child: const Text('Aspect ratio box'),
),
);
Clip
Decorates a Box
with different types of Clip
widgets
final style = Style(
clip.oval(),
);
Box(
style: style,
child: const Text('Oval box'),
);
// Equivalent to
ClipOval(
child: Box(
child: const Text('Oval box'),
),
);
Helper methods
clip.oval()
: Wraps with a ClipOval widgetclip.rrect()
: Wraps with a ClipRRect widgetclip.rect()
: Wraps with a ClipRect widgetclip.path()
: Wraps with a ClipPath widgetclip.triangle()
: Wraps with a ClipPath widget that clips to a triangle
Visibility
Decorates a Box
with a Visibility
widget
final style = Style(
visibility(false),
);
// Equivalent to
Visibility(
visible: false,
child: Box(
child: const Text('Invisible box'),
),
);
Helper methods
visibility.on()
: Wraps the Box with an Visibility widget that is visiblevisibility.off()
: Wraps the**Box**
with an**Visibility**
widget that is invisible
Flexible
Decorates a Flex
Styled widget like FlexBox
, HBox
, VBox
, with a Flexible
widget
final style = Style(
flexible(flex:1, fit: FlexFit.tight),
);
flexible(flex:1, fit: FlexFit.tight)
: Wraps theFlex
Styled widget with aFlexible
widget
Helper methods
flexible.expanded()
: Equivalent to Expanded widget, orflexible(fit: FlexFit.tight)
flexible.loose()
: Equivalent to Flexible widget, orflexible(fit: FlexFit.loose)
flexible.tight()
: Equivalent toflexible(fit: FlexFit.tight)
This is equivalent to wrapping the Flex
Styled widget with a Flexible
widget.
Flexible(
flex: 1,
fit: FlexFit.tight,
child: FlexBox(
children: [
const Text('Flexible box'),
],
),
);