求助:如何创建带侧边凸起的自定义RoundedRectangle Shape?
实现侧边带凸起的自定义圆角矩形形状
下面是用SwiftUI实现该自定义形状的代码,核心是通过自定义Path拼接基础圆角矩形和侧边凸起的路径:
import SwiftUI struct BumpedRoundedRectangle: Shape { // 基础圆角半径 var cornerRadius: CGFloat // 凸起向外延伸的横向长度 var bumpWidth: CGFloat // 凸起的垂直高度(对应半圆直径) var bumpHeight: CGFloat // 凸起位置:0为左侧,1为右侧 var bumpSide: CGFloat = 1.0 func path(in rect: CGRect) -> Path { var path = Path() // 计算凸起的垂直中心坐标 let bumpCenterY = rect.midY let halfBumpHeight = bumpHeight / 2 // 开始绘制基础圆角矩形路径 path.move(to: CGPoint(x: rect.minX, y: rect.minY + cornerRadius)) // 左上角圆角 path.addArc(center: CGPoint(x: rect.minX + cornerRadius, y: rect.minY + cornerRadius), radius: cornerRadius, startAngle: .degrees(180), endAngle: .degrees(270), clockwise: false) // 顶部边(到凸起前的位置) let topEdgeEndX = bumpSide < 0.5 ? rect.minX + cornerRadius : rect.maxX - cornerRadius - bumpWidth path.addLine(to: CGPoint(x: topEdgeEndX, y: rect.minY)) // 绘制右侧凸起 if bumpSide >= 0.5 { path.addLine(to: CGPoint(x: rect.maxX - bumpWidth, y: bumpCenterY - halfBumpHeight)) // 凸起半圆 path.addArc(center: CGPoint(x: rect.maxX, y: bumpCenterY), radius: halfBumpHeight, startAngle: .degrees(180), endAngle: .degrees(0), clockwise: false) path.addLine(to: CGPoint(x: rect.maxX - bumpWidth, y: bumpCenterY + halfBumpHeight)) path.addLine(to: CGPoint(x: rect.maxX - bumpWidth, y: rect.maxY)) } else { // 绘制左侧凸起 path.addLine(to: CGPoint(x: rect.minX + bumpWidth, y: bumpCenterY - halfBumpHeight)) // 凸起半圆 path.addArc(center: CGPoint(x: rect.minX, y: bumpCenterY), radius: halfBumpHeight, startAngle: .degrees(0), endAngle: .degrees(180), clockwise: false) path.addLine(to: CGPoint(x: rect.minX + bumpWidth, y: bumpCenterY + halfBumpHeight)) path.addLine(to: CGPoint(x: rect.minX + bumpWidth, y: rect.maxY)) } // 右下角圆角 path.addArc(center: CGPoint(x: rect.maxX - cornerRadius, y: rect.maxY - cornerRadius), radius: cornerRadius, startAngle: .degrees(90), endAngle: .degrees(0), clockwise: false) // 底部边 let bottomEdgeStartX = bumpSide < 0.5 ? rect.minX + cornerRadius + bumpWidth : rect.minX + cornerRadius path.addLine(to: CGPoint(x: bottomEdgeStartX, y: rect.maxY)) // 左下角圆角 path.addArc(center: CGPoint(x: rect.minX + cornerRadius, y: rect.maxY - cornerRadius), radius: cornerRadius, startAngle: .degrees(0), endAngle: .degrees(90), clockwise: false) // 左侧边回到起点 path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + cornerRadius)) return path } // 支持参数动画 var animatableData: AnimatablePair<AnimatablePair<CGFloat, CGFloat>, AnimatablePair<CGFloat, CGFloat>> { get { AnimatablePair(AnimatablePair(cornerRadius, bumpWidth), AnimatablePair(bumpHeight, bumpSide)) } set { cornerRadius = newValue.first.first bumpWidth = newValue.first.second bumpHeight = newValue.second.first bumpSide = newValue.second.second } } } // 使用示例 struct BumpedRectangleDemo: View { var body: some View { BumpedRoundedRectangle(cornerRadius: 16, bumpWidth: 20, bumpHeight: 40) .fill(Color.blue) .frame(width: 200, height: 120) .padding() } } #Preview { BumpedRectangleDemo() }
参数说明
cornerRadius: 基础圆角矩形的圆角半径bumpWidth: 凸起向外延伸的横向长度bumpHeight: 凸起的垂直高度bumpSide: 控制凸起位置,0对应左侧,1对应右侧
你可以根据需求调整这些参数匹配目标形状,若需要凸起为圆角矩形而非半圆,只需将addArc部分替换为对应的圆角矩形路径即可。
内容的提问来源于stack exchange,提问作者Rebin A. Dev
相关产品推荐
相关产品推荐

