You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Flutter CustomPainter实现带圆角与阴影的三角组件

Flutter:实现带圆角和阴影的三角形组件优化需求

目标效果

目标三角形效果

当前实现效果

当前实现效果

我尝试通过CustomPainter绘制三角形,并结合Stack添加阴影,但结果未达预期,以下是现有代码:

左侧三角形代码

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(color: color.shadow, radius: radius),
              child: Container(
                padding: EdgeInsets.only(
                  top: 10.h,
                  right: 14.w,
                  left: 10.w,
                  bottom: 14.h,
                ),
                child: const Text(' '),
              ),
            ),
            CustomPaint(
              painter: _RoundedTrianglePainter(
                color: color.card,
                radius: radius,
              ),
              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({required this.color, required this.radius});

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill;

    final Path path = Path();

    // 左侧弧形起始
    path.moveTo(0 + radius, size.height / 2 - radius);
    path.quadraticBezierTo(
      0,
      size.height / 2,
      0 + radius, size.height / 2 + radius,
    );

    // 右下角圆角
    path.lineTo(size.width - radius, size.height);
    path.quadraticBezierTo(
      size.width,
      size.height,
      size.width, size.height - radius,
    );

    // 右上角圆角
    path.lineTo(size.width, radius);
    path.quadraticBezierTo(
      size.width,
      0,
      size.width - radius, 0,
    );

    path.close();
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

右侧三角形代码

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(color: color.shadow, radius: radius),
              child: Container(
                padding: EdgeInsets.only(
                  top: 10.h,
                  right: 14.w,
                  left: 10.w,
                  bottom: 14.h,
                ),
                child: const Text(' '),
              ),
            ),
            CustomPaint(
              painter: _RoundedTrianglePainter(
                color: color.card,
                radius: radius,
              ),
              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({required this.color, this.radius = 2});

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill;

    final Path path = Path();

    // 左上角圆角
    path.moveTo(radius, 0);
    path.quadraticBezierTo(
      0,
      0,
      0, radius,
    );

    // 左下角圆角
    path.lineTo(0, size.height - radius);
    path.quadraticBezierTo(
      0,
      size.height,
      radius, size.height,
    );

    // 右侧弧形
    path.lineTo(size.width - radius, size.height / 2 + radius);
    path.quadraticBezierTo(
      size.width,
      size.height / 2,
      size.width - radius,
      size.height / 2 - radius,
    );

    path.close();
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

组件使用示例

LeftTriangle(
  color: Colors.green,
  child: Text(
    "number",
    style: TextStyle(
      color: Colors.white,
      fontWeight: FontWeight.bold,
    ),
  ),
),

具体问题

  • 圆角处理:三角形的圆角未按设计要求正确呈现
  • 阴影效果:阴影与三角形融合度差,视觉效果不自然
  • 整体形状:最终绘制的三角形形状与设计目标不符

请帮忙优化代码,解决上述问题,实现符合设计要求的带圆角和阴影的三角形组件。


内容的提问来源于stack exchange,提问作者Ifqy Gifha azhar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:35:55