Reputation: 23
How to make a container having shape like the image shown below. 👇
width = 300 and height = 130
The Two semicircles should be aligned at centre of the height of container
Please click on "Card" to see image
Upvotes: 2
Views: 1543
Reputation: 12575
You can try with custom painter.
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
DateTime date = DateTime.now();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white54,
body: SafeArea(
child: Container(
child: Center(
child: Container(
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(10)
),
height: 100,
width: 200,
child: Stack(
clipBehavior: Clip.antiAlias,
children: [
Positioned(
left: -15,
bottom: 35,
child: Container(
height: 30,
width: 30,
child: CustomPaint(
painter: MyPainter(),
),
)),
Positioned(
right: -15,
bottom: 30.5,
child: Container(
height: 30,
width: 35,
child: CustomPaint(
painter: MyPainter(),
),
),
)
],
)),
),
),
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()..color = Colors.white;
canvas.drawArc(
Rect.fromCenter(
center: Offset(size.height / 2, size.width / 2),
height: size.height,
width: size.width,
),
math.pi * 2,
math.pi * 2,
true,
paint,
);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
output:
N.B: Adjust your color and circle height and width as you need
Upvotes: 1
Reputation: 1396
You need to use custom clippers.
Here's an example on that,
class CardClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
final Path path = Path();
path.lineTo(0.0, size.height / 2 - 4);
path.relativeArcToPoint(const Offset(0, 30),
radius: const Radius.circular(10.0), largeArc: true);
path.lineTo(0.0, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, size.height / 2 + 26);
path.arcToPoint(Offset(size.width, size.height / 2 - 4),
radius: const Radius.circular(10.0), clockwise: true);
path.lineTo(size.width, 0);
path.lineTo(0.0, 0.0);
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
Okay, that's about the clipper, we can now use it, but it won't provide us with shadow.
To cast shadows to clipper objects, we'll use Clip Shadow package.
Now, we'll implement CardClipper
with actual Clip
Widget, in this case, ClipShadow
,
ClipShadow(
clipper: CardClipper(),
boxShadow: [
BoxShadow(
offset: Offset(0, 4),
blurRadius: 18,
color: Color.fromRGBO(0, 0, 0, 0.1)),
],
child: Card(...)
);
Try playing with values in the clipper until you get the desired output.
Upvotes: 3