Reputation: 33
I am trying to create a triangle shape with rounded corners and a shadow using Flutter's CustomPainter. My goal is to achieve a design similar to this:
I attempted to implement it using CustomPainter and wrapped the painter in a Stack to add a shadow effect. However, the result is not as expected—the corners of the triangle are not rounded properly, and the shadow appears imperfect:
Below is my current implementation for the left and right triangles:
left triangle
import 'package:custom_widget_component/core/widgets/button_shadow/model_color/card_color_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class LeftTriangle extends StatelessWidget {
final Widget child;
final double radius;
final CardColorModel color;
const LeftTriangle({
super.key,
required this.child,
this.radius = 2,
required this.color,
});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
return Stack(
children: [
CustomPaint(
painter: _RoundedTrianglePainter(radius: radius, color.shadow),
child: Container(
padding: EdgeInsets.only(
top: 10.h,
right: 14.w,
left: 10.w,
bottom: 14.h,
),
child: const Text(' '),
),
),
CustomPaint(
painter: _RoundedTrianglePainter(
radius: radius,
color.card,
),
child: Container(
padding: EdgeInsets.only(
left: 9.w,
right: 8.w,
top: 12.h,
bottom: 8.h,
),
child: child,
),
),
],
);
},
);
}
}
class _RoundedTrianglePainter extends CustomPainter {
final double radius;
final Color color;
_RoundedTrianglePainter(this.color,
{required this.radius}); // Default radius lengkung keluar
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()
..color = color // Ubah warna sesuai kebutuhan
..style = PaintingStyle.fill;
final Path path = Path();
// Mulai dari sudut atas kiri (dengan lengkung keluar)
path.moveTo(0 + radius, size.height / 2 - radius);
path.quadraticBezierTo(
0, // Titik kontrol (melengkung keluar di sisi kiri atas)
size.height / 2, // Lokasi kontrol
0 + radius, size.height / 2 + radius, // Posisi setelah lengkungan
);
// Garis ke kanan bawah (dengan lengkung keluar)
path.lineTo(size.width - radius, size.height);
path.quadraticBezierTo(
size.width, // Titik kontrol (melengkung keluar di sudut kanan bawah)
size.height, // Lokasi kontrol
size.width, size.height - radius, // Posisi setelah lengkungan
);
// Garis ke kanan atas (dengan lengkung keluar)
path.lineTo(size.width, radius);
path.quadraticBezierTo(
size.width, // Titik kontrol (melengkung keluar di sudut kanan atas)
0, // Lokasi kontrol
size.width - radius, 0, // Posisi setelah lengkungan
);
// Tutup path
path.close();
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
right triangle
import 'package:custom_widget_component/core/widgets/button_shadow/model_color/card_color_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class RightTriangle extends StatelessWidget {
final Widget child;
final double radius;
final CardColorModel color;
const RightTriangle(
{super.key, required this.child, this.radius = 4, required this.color});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
return Stack(
children: [
CustomPaint(
painter: _RoundedTrianglePainter(radius: radius, color.shadow),
child: Container(
padding: EdgeInsets.only(
top: 10.h,
right: 14.w,
left: 10.w,
bottom: 14.h,
),
child: const Text(' '),
),
),
CustomPaint(
painter: _RoundedTrianglePainter(
radius: radius,
color.card,
),
child: Container(
padding: EdgeInsets.only(
left: 9.w,
right: 8.w,
top: 12.h,
bottom: 8.h,
),
child: child,
),
),
],
);
},
);
}
}
class _RoundedTrianglePainter extends CustomPainter {
final double radius;
final Color color;
_RoundedTrianglePainter(this.color,
{this.radius = 2}); // Default radius lengkung keluar
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()
..color = color // Ubah warna sesuai kebutuhan
..style = PaintingStyle.fill;
final Path path = Path();
// Mulai dari sudut atas (dengan lengkung keluar)
path.moveTo(radius, 0);
path.quadraticBezierTo(
0, // Titik kontrol (melengkung keluar dari sudut atas)
0, // Lokasi kontrol
0, radius, // Posisi setelah lengkungan
);
// Garis ke sudut kiri bawah (dengan lengkung keluar)
path.lineTo(0, size.height - radius);
path.quadraticBezierTo(
0, // Titik kontrol (melengkung keluar dari sudut kiri bawah)
size.height, // Lokasi kontrol
radius, size.height, // Posisi setelah lengkungan
);
// Garis ke kanan (sisi miring segitiga)
path.lineTo(size.width - radius, size.height / 2 + radius);
path.quadraticBezierTo(
size.width, // Titik kontrol (melengkung keluar di sisi kanan)
size.height / 2, // Lokasi kontrol
size.width - radius,
size.height / 2 - radius, // Posisi setelah lengkungan
);
// Tutup path
path.close();
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
example use the widget
LeftTriangle(
color: Colors.green,
child: Text(
"number",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
Issues I'm Facing: Rounded Corners: The corners of my triangle are not rounded properly as per the desired design. Shadow: The shadow effect doesn't blend well with the triangle, and it doesn't look natural. Overall Shape: The final shape doesn’t match my design goal.
Upvotes: 0
Views: 90