SwiftUI中strokeBorder为何无法贴合边界?
解决SwiftUI自定义InsettableShape描边(strokeBorder)超出边界问题
你的问题出在InsettableShape的实现逻辑上——strokeBorder会自动帮你处理描边的边界适配,但你手动在path(in:)里对rect做了额外inset,导致路径偏移,描边超出容器。
问题原因
strokeBorder的工作逻辑是:
- 根据线宽计算需要向内缩进的距离(线宽的一半)
- 调用你实现的
inset(by:)方法更新形状的inset值 - 把原容器rect向内缩进对应距离后的新rect传入
path(in:)方法 - 基于这个新rect绘制路径,描边就会刚好贴合原容器边界
但你在path(in:)里又对传入的rect做了一次insetBy(dx: insetAmount, dy: insetAmount),相当于做了两次缩进,导致路径缩小,描边自然就超出了原容器的边界。
修复方案
直接去掉path(in:)里的手动inset操作,基于系统传入的rect构建路径即可:
import SwiftUI struct ContentView: View { var body: some View { let myCustomInsettableShape = TestShape() ZStack { myCustomInsettableShape .fill(Color.white) myCustomInsettableShape .strokeBorder(Color.black.opacity(0.5), style: StrokeStyle(lineWidth: 50.0, lineCap: .round, lineJoin: .miter)) } .background(Color.red) .padding(50) } } struct TestShape: InsettableShape { var insetAmount: CGFloat = .zero func path(in rect: CGRect) -> Path { // 直接使用系统传入的rect,无需手动inset Path { path in path.move(to: CGPoint(x: rect.minX, y: rect.midY)) path.addLine(to: CGPoint(x: rect.midX, y: rect.minY)) path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY)) path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY)) path.closeSubpath() } } func inset(by amount: CGFloat) -> some InsettableShape { var myShape = self myShape.insetAmount += amount return myShape } }
修复后逻辑
当你调用strokeBorder时:
- SwiftUI自动计算出需要缩进25(50线宽的一半)
- 调用
inset(by:25)更新insetAmount - 把原容器rect向内缩进25后的rect传入
path(in:) - 你基于这个缩进后的rect绘制路径,描边会刚好覆盖在原容器的边界内侧,不会超出红色背景区域。
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

