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

如何在Flutter中用Canvas绘制带圆角的水平菱形(Rhombus)

为Flutter菱形组件添加圆角的实现方案

要实现带圆角的菱形,确实需要通过Path的arcToPoint方法手动绘制每个角的圆弧——RRect无法直接适配菱形的斜向边角。以下是基于你现有代码完善后的实现:

import 'package:flutter/material.dart';

/// Diamond Widget
class Diamond extends StatelessWidget {
  /// Constructor
  const Diamond({
    required this.width,
    required this.height,
    this.lineColor = Colors.black,
    this.cornerRadius = 8.0,
    super.key,
  });

  /// Width of the diamond
  final double width;

  /// Height of the diamond
  final double height;

  /// Outline's color of the diamond
  final Color lineColor;

  /// Corner radius of the diamond
  final double cornerRadius;

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: Size(width, height),
      painter: _DiamondPainter(
        lineColor: lineColor,
        cornerRadius: cornerRadius,
      ),
    );
  }
}

/// Custom painter for drawing a diamond
class _DiamondPainter extends CustomPainter {
  _DiamondPainter({required this.lineColor, required this.cornerRadius});

  final Color lineColor;
  final double cornerRadius;

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
      ..style = PaintingStyle.stroke
      ..color = lineColor
      ..strokeWidth = 2.0
      ..strokeJoin = StrokeJoin.round; // 优化线条衔接处的平滑度

    // 限制圆角最大值,避免超过菱形可容纳的范围导致变形
    final double safeRadius = min(
      cornerRadius,
      min(size.width / 4, size.height / 4),
    );

    final halfWidth = size.width / 2;
    final halfHeight = size.height / 2;

    final Path path = Path()
      // 顶部圆角:从右侧端点开始
      ..moveTo(halfWidth + safeRadius, 0)
      // 绘制顶部内凹圆弧到左侧端点
      ..arcToPoint(
        Offset(halfWidth - safeRadius, 0),
        radius: Radius.circular(safeRadius),
        clockwise: false,
      )
      // 绘制左侧边到左侧圆角的上端点
      ..lineTo(0, halfHeight - safeRadius)
      // 绘制左侧内凹圆弧到左侧圆角的下端点
      ..arcToPoint(
        Offset(0, halfHeight + safeRadius),
        radius: Radius.circular(safeRadius),
        clockwise: false,
      )
      // 绘制底部边到底部圆角的左端点
      ..lineTo(halfWidth - safeRadius, size.height)
      // 绘制底部内凹圆弧到底部圆角的右端点
      ..arcToPoint(
        Offset(halfWidth + safeRadius, size.height),
        radius: Radius.circular(safeRadius),
        clockwise: false,
      )
      // 绘制右侧边到右侧圆角的下端点
      ..lineTo(size.width, halfHeight + safeRadius)
      // 绘制右侧内凹圆弧到右侧圆角的上端点
      ..arcToPoint(
        Offset(size.width, halfHeight - safeRadius),
        radius: Radius.circular(safeRadius),
        clockwise: false,
      )
      // 闭合路径
      ..close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant _DiamondPainter oldDelegate) {
    return lineColor != oldDelegate.lineColor ||
        cornerRadius != oldDelegate.cornerRadius;
  }
}

核心细节说明

  1. 安全圆角限制:通过safeRadius把圆角半径控制在菱形宽度/4、高度/4的最小值以内,避免圆角过大导致图形结构异常。
  2. 圆弧绘制逻辑:每个圆角都遵循「移动到圆弧端点→绘制内凹圆弧→连接下一段直线」的流程,clockwise: false确保圆弧向菱形内部弯曲。
  3. 线条衔接优化:添加strokeJoin: StrokeJoin.round,让线条与圆弧的衔接处更平滑,消除尖锐棱角。
  4. 重绘逻辑优化:修改shouldRepaint方法,仅当颜色或圆角参数变化时触发重绘,提升性能。

内容的提问来源于stack exchange,提问作者Hamed Heydarian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:40:10