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

Flutter中如何绘制自定义圆角矩形边框(ShapeBorder)?

解决ShapeBorder扩展中边框角与矩形不匹配的问题

嘿,我之前自定义ShapeBorder的时候也踩过这个坑!咱们来拆解一下问题根源,再给你修正后的代码参考:

最可能的两个问题点

  • 未处理边框宽度的偏移:当设置了borderWidth时,实际绘制边框的区域应该是原矩形向内收缩borderWidth/2的范围——如果直接用原始矩形绘制,边框会一半在矩形外、一半在矩形内,视觉上就会出现圆角和矩形角错位的情况。
  • BorderRadius的解析与应用错误:BorderRadius需要根据布局方向解析后再使用,而且要基于收缩后的矩形生成圆角路径,不然圆角的圆心位置会偏差。

修正后的CustomRoundedRectangleBorder示例

class CustomRoundedRectangleBorder extends ShapeBorder {
  final double borderWidth;
  final BorderRadius borderRadius;

  const CustomRoundedRectangleBorder({
    this.borderWidth = 1.0,
    this.borderRadius = BorderRadius.zero,
  }) : assert(borderWidth >= 0),
       assert(borderRadius != null);

  @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.all(borderWidth);

  @override
  ShapeBorder scale(double t) => CustomRoundedRectangleBorder(
        borderWidth: borderWidth * t,
        borderRadius: borderRadius * t,
      );

  @override
  Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
    final resolvedRadius = borderRadius.resolve(textDirection);
    final innerRect = rect.deflate(borderWidth);
    return Path()
      ..addRRect(resolvedRadius.toRRect(innerRect));
  }

  @override
  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
    final resolvedRadius = borderRadius.resolve(textDirection);
    return Path()
      ..addRRect(resolvedRadius.toRRect(rect));
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = borderWidth
      ..color = Colors.black; // 可替换为你需要的边框颜色

    final resolvedRadius = borderRadius.resolve(textDirection);
    // 关键步骤:向内收缩矩形,让边框居中贴合原矩形边缘
    final borderRect = rect.deflate(borderWidth / 2);
    final borderRRect = resolvedRadius.toRRect(borderRect);

    canvas.drawRRect(borderRRect, paint);
  }
}

调试小技巧

  • 可以临时在paint方法里用不同颜色绘制原始矩形rect和收缩后的borderRect,直观查看两者的位置关系:
    canvas.drawRect(rect, Paint()..color = Colors.red.withOpacity(0.3));
    canvas.drawRect(borderRect, Paint()..color = Colors.blue.withOpacity(0.3));
    
  • 打印rect和borderRect的坐标值,确认收缩后的区域是否符合预期。

内容的提问来源于stack exchange,提问作者Bram Vanbilsen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:40:03