Reputation: 2923
I have this piece of code.
Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(18),
),
child: Center(
child: Text(
'Monday',
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
),
);
That produces this
But I want something that looks like this.
Upvotes: 1
Views: 1967
Reputation: 354
You have to write a CustomPainter
class to achieve this, luckily there's a site which generates code for a given svg
or use Nested Stack
with Container
. This example gives the one which you expected.
CustomPainter
class
class RPSCustomPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
Path path_0 = Path();
path_0.moveTo(size.width * 0.1898734, 0);
path_0.lineTo(size.width * 0.06962025, 0);
path_0.cubicTo(size.width * 0.03117006, 0, 0, size.height * 0.03117006, 0,
size.height * 0.06962025);
path_0.lineTo(0, size.height * 0.1835443);
path_0.lineTo(size.width * 0.02531646, size.height * 0.1835443);
path_0.lineTo(size.width * 0.02531646, size.height * 0.06962025);
path_0.cubicTo(
size.width * 0.02531646,
size.height * 0.04515196,
size.width * 0.04515196,
size.height * 0.02531646,
size.width * 0.06962025,
size.height * 0.02531646);
path_0.lineTo(size.width * 0.1898734, size.height * 0.02531646);
path_0.lineTo(size.width * 0.1898734, 0);
path_0.close();
path_0.moveTo(size.width * 0.1898734, size.height * 0.9746835);
path_0.lineTo(size.width * 0.06962025, size.height * 0.9746835);
path_0.cubicTo(
size.width * 0.04515196,
size.height * 0.9746835,
size.width * 0.02531646,
size.height * 0.9548481,
size.width * 0.02531646,
size.height * 0.9303797);
path_0.lineTo(size.width * 0.02531646, size.height * 0.8164557);
path_0.lineTo(0, size.height * 0.8164557);
path_0.lineTo(0, size.height * 0.9303797);
path_0.cubicTo(0, size.height * 0.9688291, size.width * 0.03117006,
size.height, size.width * 0.06962025, size.height);
path_0.lineTo(size.width * 0.1898734, size.height);
path_0.lineTo(size.width * 0.1898734, size.height * 0.9746835);
path_0.close();
path_0.moveTo(size.width * 0.8227848, size.height);
path_0.lineTo(size.width * 0.8227848, size.height * 0.9746835);
path_0.lineTo(size.width * 0.9303797, size.height * 0.9746835);
path_0.cubicTo(
size.width * 0.9548481,
size.height * 0.9746835,
size.width * 0.9746835,
size.height * 0.9548481,
size.width * 0.9746835,
size.height * 0.9303797);
path_0.lineTo(size.width * 0.9746835, size.height * 0.8164557);
path_0.lineTo(size.width, size.height * 0.8164557);
path_0.lineTo(size.width, size.height * 0.9303797);
path_0.cubicTo(size.width, size.height * 0.9688291, size.width * 0.9688291,
size.height, size.width * 0.9303797, size.height);
path_0.lineTo(size.width * 0.8227848, size.height);
path_0.close();
path_0.moveTo(size.width * 0.8227848, size.height * 0.02531646);
path_0.lineTo(size.width * 0.8227848, 0);
path_0.lineTo(size.width * 0.9303797, 0);
path_0.cubicTo(size.width * 0.9688291, 0, size.width,
size.height * 0.03117006, size.width, size.height * 0.06962025);
path_0.lineTo(size.width, size.height * 0.1835443);
path_0.lineTo(size.width * 0.9746835, size.height * 0.1835443);
path_0.lineTo(size.width * 0.9746835, size.height * 0.06962025);
path_0.cubicTo(
size.width * 0.9746835,
size.height * 0.04515196,
size.width * 0.9548481,
size.height * 0.02531646,
size.width * 0.9303797,
size.height * 0.02531646);
path_0.lineTo(size.width * 0.8227848, size.height * 0.02531646);
path_0.close();
Paint paint_0_fill = Paint()..style = PaintingStyle.fill;
paint_0_fill.color = Color(0xff181717).withOpacity(1.0);
canvas.drawPath(path_0, paint_0_fill);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
and use it like so
Stack(
alignment: Alignment.bottomCenter,
children: [
Stack(
alignment: Alignment.center,
children: [
Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(18),
),
child: Center(
child: Text(
'Monday',
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
),
),
Padding(
padding: EdgeInsets.all(24),
child: CustomPaint(
size: Size(180, 180),
painter: RPSCustomPainter(),
),
),
],
),
Padding(
padding: EdgeInsets.only(bottom: 24),
child: ClipRRect(
borderRadius: BorderRadius.circular(100),
child: Container(
padding: EdgeInsets.all(4),
color: Colors.black,
child: Icon(
Icons.close,
color: Colors.white,
size: 16,
),
),
),
),
],
),
Upvotes: 1
Reputation: 63799
By Knowing CustomPainter
widget's paint
class MyCustomPainter extends CustomPainter {
final double padding;
final double frameSFactor;
MyCustomPainter({
required this.padding,
required this.frameSFactor,
});
@override
void paint(Canvas canvas, Size size) {
final frameHWidth = size.width * frameSFactor;
Paint paint = Paint()
..color = Colors.redAccent
..strokeCap = StrokeCap.round
..style = PaintingStyle.fill
..strokeWidth = 4;
/// background
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTRB(0, 0, size.width, size.height),
Radius.circular(18),
),
paint);
/// top left
canvas.drawLine(
Offset(0 + padding, padding),
Offset(
padding + frameHWidth,
padding,
),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(0 + padding, padding),
Offset(
padding,
padding + frameHWidth,
),
paint..color = Colors.black,
);
/// top Right
canvas.drawLine(
Offset(size.width - padding, padding),
Offset(size.width - padding - frameHWidth, padding),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(size.width - padding, padding),
Offset(size.width - padding, padding + frameHWidth),
paint..color = Colors.black,
);
/// Bottom Right
canvas.drawLine(
Offset(size.width - padding, size.height - padding),
Offset(size.width - padding - frameHWidth, size.height - padding),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(size.width - padding, size.height - padding),
Offset(size.width - padding, size.height - padding - frameHWidth),
paint..color = Colors.black,
);
/// Bottom Left
canvas.drawLine(
Offset(0 + padding, size.height - padding),
Offset(0 + padding + frameHWidth, size.height - padding),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(0 + padding, size.height - padding),
Offset(0 + padding, size.height - padding - frameHWidth),
paint..color = Colors.black,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true; //based on your use-cases
}
And use Like
SizedBox(
height: 200,
width: 200,
child: CustomPaint(
painter: MyCustomPainter(frameSFactor: .1, padding: 20),
child: Center(
child: Text(
'With Painter',
style: TextStyle(
color: Colors.black,
fontSize: 30,
),
),
),
),
),
Also using Container decoration
class CustomDecoration extends Decoration {
final Color? backgroundColor;
final double frameSFactor;
//defalut padding _Need to check
final double gap;
CustomDecoration({
this.backgroundColor = Colors.transparent,
required this.frameSFactor,
required this.gap,
});
@override
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
return CustomDecorationPainter(
backgroundColor: backgroundColor!,
frameSFactor: frameSFactor,
padding: gap);
}
}
class CustomDecorationPainter extends BoxPainter {
final Color backgroundColor;
final double frameSFactor;
final double padding;
CustomDecorationPainter({
required this.backgroundColor,
required this.frameSFactor,
required this.padding,
});
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
print(configuration.size!.height);
final Rect bounds = offset & configuration.size!;
final frameHWidth = configuration.size!.width * frameSFactor;
Paint paint = Paint()
..color = backgroundColor
..strokeCap = StrokeCap.round
..style = PaintingStyle.fill
..strokeWidth = 4;
/// background
canvas.drawRRect(
RRect.fromRectAndRadius(
bounds,
Radius.circular(18),
),
paint..color = Colors.redAccent);
paint.color = Colors.black;
/// top left
canvas.drawLine(
bounds.topLeft + Offset(padding, padding),
Offset(bounds.topLeft.dx + frameHWidth, bounds.topLeft.dy) +
Offset(padding, padding),
paint,
);
canvas.drawLine(
bounds.topLeft + Offset(padding, padding),
Offset(bounds.topLeft.dx, bounds.topLeft.dy + frameHWidth) +
Offset(padding, padding),
paint,
);
//top Right
canvas.drawLine(
Offset(bounds.topRight.dx - padding, bounds.topRight.dy + padding),
Offset(bounds.topRight.dx - padding - frameHWidth,
bounds.topRight.dy + padding),
paint,
);
canvas.drawLine(
Offset(bounds.topRight.dx - padding, bounds.topRight.dy + padding),
Offset(bounds.topRight.dx - padding,
bounds.topRight.dy + padding + frameHWidth),
paint..color,
);
//bottom Right
canvas.drawLine(
Offset(bounds.bottomRight.dx - padding, bounds.bottomRight.dy - padding),
Offset(bounds.bottomRight.dx - padding,
bounds.bottomRight.dy - padding - frameHWidth),
paint,
);
canvas.drawLine(
Offset(bounds.bottomRight.dx - padding, bounds.bottomRight.dy - padding),
Offset(bounds.bottomRight.dx - padding - frameHWidth,
bounds.bottomRight.dy - padding),
paint,
);
//bottom Left
canvas.drawLine(
Offset(bounds.bottomLeft.dx + padding, bounds.bottomLeft.dy - padding),
Offset(bounds.bottomLeft.dx + padding,
bounds.bottomLeft.dy - padding - frameHWidth),
paint,
);
canvas.drawLine(
Offset(bounds.bottomLeft.dx + padding, bounds.bottomLeft.dy - padding),
Offset(bounds.bottomLeft.dx + padding + frameHWidth,
bounds.bottomLeft.dy - padding),
paint,
);
}
}
And use like
SizedBox(
width: 200,
height: 200,
child: Container(
alignment: Alignment.center,
decoration: CustomDecoration(
frameSFactor: .1,
gap: 20,
),
child: Text("With Decoration"),
),
),
you can add the button the way you like
Upvotes: 6