Ifqy Gifha azhar
Ifqy Gifha azhar

Reputation: 33

How to make radius & border in corner triangle using custom painter in flutter

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: triangle

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:

triangle

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

Answers (0)

Related Questions