Flutter. Material 3 Expressive Shapes

Flutter. Material 3 Expressive Shapes

FlutterPulse

This article was translated specially for the channel FlutterPulseYou'll find lots of interesting things related to Flutter on this channel. Don't hesitate to subscribe!🚀

And how to use them in your Flutter app.

Material 3 Expressive is an expansion of Google's Material design system that adds new components, features, and design tactics to create more emotionally impactful and dynamic user experiences.

One of those new design components is the Shape library.

Unfortunately, there is still no support in Flutter, but fortunately, an active community member has already created a package for that.

If you are a member, please continue,otherwise, read the full story here.

Installation

flutter pub add flutter_m3shapes

Usage

Practically, we can shape anything with it.

Basic example with colored M3Container s.

                   M3Container.pixelTriangle(
color: Colors.deepOrange,
width: 100,
height: 100,
child: const Center(child: Text("pixelTriangle")),
),

Very easy to use, as we can see.
There is also a constructor that takes the shape as a positional argument, so the above can be rewritten as:

                    M3Container(
Shapes.pixel_triangle,
color: Colors.deepOrange,
width: 100,
height: 100,
child: const Center(child: Text("pixelTriangle")),
),

This constructor allows creating custom components that take the shape as an argument, or changing the shape dynamically.

Profile images

                   M3Container(
Shapes.flower,
clipBehavior: Clip.antiAlias,
width: 100,
height: 100,
child: Image.network(
'https://i.pravatar.cc/150?img=5',
),
),

M3Containeris kind of a mix of Containerwith ClipRector ClipOval, but easier to use and with a lot of predefined shapes.

Shaped buttons

I recalled myself as also a creative member of the community and made the EzShapedButtonclass.

Here is what it looks like:

Looks funny, right?

We can choose any shape and supply it to the constructor:

                EzShapedButton(
shape: Shapes.ghostish,
color: Colors.cyan.shade900,
width: 150,
height: 60,
child: Ez3dText(
'Click me!',
fontSize: 18,
),
),

Here is the button class itself:

final class EzShapedButton extends StatelessWidget {
final Widget? child;
final GestureTapCallback? onTap;
final double? width;
final double? height;
final Color? color;
final Shapes shape;

const EzShapedButton(
{super.key,
this.child,
this.onTap,
this.width = double.infinity,
this.height = 60,
this.color = Colors.green,
required this.shape,});

@override
Widget build(Object context) {
return EzScaleOnTap(
onTap: onTap,
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: M3Container(
shape,
width: width,
height: height,
color: color,
clipBehavior: Clip.antiAlias,
child: Center(child: child),
),
));
}
}

You will need EzScaleOnTap:


final class EzScaleOnTap extends StatefulWidget {
final double? diff;
final Widget child;
final GestureTapCallback? onTap;

const EzScaleOnTap({super.key, this.diff = -0.05,
required this.child, this.onTap});

@override
State<StatefulWidget> createState() {
return _ScaleState();
}
}

class _ScaleState extends State<EzScaleOnTap> {
double _scale = 1;

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onTap,
onTapDown: (_) => setState(() => _scale += widget.diff!),
onTapUp: (_) => setState(() => _scale = 1.0),
child: Transform.scale(
scale: _scale,
child: widget.child,
),
);
}
}

Ez3dTextisn't required, regular Textcan be used instead, but anyway:

class Ez3dText extends StatelessWidget {
final String text;
final double fontSize;
final Color color;
final Color shadowColor;
final int depth;

const Ez3dText(this.text, {
super.key,
this.fontSize = 18,
this.color = Colors.white,
this.shadowColor = Colors.black,
this.depth = 3,
});

@override
Widget build(BuildContext context) {
return Stack(
children: [
// Create shadow layers
for (int i = depth; i > 0; i--)
Positioned(
left: i.toDouble(),
top: i.toDouble(),
child: Text(
text,
style: TextStyle(
fontSize: fontSize,
color: shadowColor.withValues(alpha: 0.3),
fontWeight: FontWeight.bold,
),
),
),
// Main text on top
Text(
text,
style: TextStyle(
fontSize: fontSize,
color: color,
fontWeight: FontWeight.bold,
),
),
],
);
}
}

Conclusion

flutter_m3shapes is a nice package, easy to use and useful.

Thank you for reading, and happy coding!

Report Page