I have the following design. How can I implement it in Flutter? I tried using a stack with the image at the bottom and a frame on top using a .png, but I don’t think that’s the best solution. Is there a better approach?
2
the appropriate approach would be to apply a CustomClipper.
CustomClipper
Here is an article to explain the topic : https://medium.com/flutter-community/flutter-custom-clipper-28c6d380fdd6
So you have to create your custom class that extends the CustomClipper.
Example (that doesn’t suit your case) :
class MyCustomClipper extends CustomClipper<Path> { @override Path getClip(Size size) { final path = Path() ..lineTo(0.0, size.height) ..lineTo(size.width, size.height) ..lineTo(size.width, 0.0) ..quadraticBezierTo(size.width, 0.0, size.width - 20.0, 0.0) ..lineTo(40.0, 70.0) ..quadraticBezierTo(10.0, 85.0, 0.0, 120.0) ..close(); return path; } @override bool shouldReclip(CustomClipper<Path> oldClipper) { return true; } }
This code comes from the flutter_custom_clippers (you can find some cool example in here).
Then you can use it on your image as follow :
ClipPath( clipper: MyCustomClipper(), child: MyImageWidget(), ), )
Now all you have to do is discover the possibility of CustomClipper and create the class that match your case.
In order to achieve that, you must use a CustomClipper, check this code
class ImageClipper extends CustomClipper<Path> { final double radius; ImageClipper({ this.radius = 80, }); @override Path getClip(Size size) { final leftHeight = size.height * 0.9; return Path() ..moveTo(0.0, radius) ..lineTo(0.0, size.height - radius) // Bottom Left ..quadraticBezierTo( 0.0, size.height, radius, size.height, ) ..lineTo(size.width - radius, leftHeight) // Bottom Right ..quadraticBezierTo( size.width, leftHeight - 4, size.width, leftHeight - radius, ) ..lineTo(size.width, 0.0 + radius) // Top Right ..quadraticBezierTo( size.width, 0.0, size.width - radius, 0.0, ) ..lineTo(0.0 + radius, 0.0) // Top Left ..quadraticBezierTo( 0.0, 0.0, 0.0, radius, ) ..close(); } @override bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true; }
and here is an example of how to use it
import 'package:flutter/material.dart'; const imageUrl = 'https://images.pexels.com/photos/268533/pexels-photo-268533.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500'; class TempPage extends StatelessWidget { const TempPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.amber, appBar: AppBar( title: const Text('Image clipped'), ), body: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Image.network( imageUrl, height: 300, width: 200, fit: BoxFit.fill, ), ClipPath( clipper: ImageClipper( radius: 20, ), child: Image.network( imageUrl, height: 300, width: 200, fit: BoxFit.fill, ), ), ], ), ); } }
remember to change shouldReclip to false if needed
shouldReclip
Click here to cancel reply.
2
Answers
the appropriate approach would be to apply a
CustomClipper
.Here is an article to explain the topic : https://medium.com/flutter-community/flutter-custom-clipper-28c6d380fdd6
So you have to create your custom class that extends the CustomClipper.
Example (that doesn’t suit your case) :
This code comes from the flutter_custom_clippers (you can find some cool example in here).
Then you can use it on your image as follow :
Now all you have to do is discover the possibility of CustomClipper and create the class that match your case.
In order to achieve that, you must use a CustomClipper, check this code
and here is an example of how to use it
remember to change
shouldReclip
to false if needed