Swift中使用UIBezierPath绘制适配内容的类iPhone刘海曲线视图问题
解决iPhone刘海式曲线视图的绘制需求
问题描述
使用Swift的UIBezierPath绘制类似iPhone刘海的曲线视图,当前实现的中间为弧形,需求改为中间直线段,且中间直线的宽度能随内容尺寸动态调整。
- 当前效果:顶部中间为向下凹陷的弧形
- 期望效果:顶部中间为水平直线,两侧是平滑的弧形过渡到顶部边缘
修改后的代码实现
class CurveView: UIView { // 可配置的刘海中间直线宽度,可根据内容动态调整 var notchWidth: CGFloat = 80 { didSet { addShape() } } private let notchHeight: CGFloat = 20 private var shapeLayer: CALayer? override func layoutSubviews() { super.layoutSubviews() addShape() } private func addShape() { let shapeLayer = CAShapeLayer() shapeLayer.path = createPath() shapeLayer.strokeColor = UIColor.lightGray.cgColor shapeLayer.fillColor = UIColor.red.cgColor shapeLayer.lineWidth = 1 shapeLayer.shadowOffset = CGSize(width: 0, height: 0) shapeLayer.shadowRadius = 5 shapeLayer.shadowColor = UIColor.gray.cgColor shapeLayer.shadowOpacity = 0.3 if let oldShapeLayer = self.shapeLayer { layer.replaceSublayer(oldShapeLayer, with: shapeLayer) } else { layer.insertSublayer(shapeLayer, at: 0) } self.shapeLayer = shapeLayer } private func createPath() -> CGPath { let path = UIBezierPath() let viewWidth = bounds.width let halfNotchWidth = notchWidth / 2 let leftNotchEndX = (viewWidth / 2) - halfNotchWidth let rightNotchStartX = (viewWidth / 2) + halfNotchWidth // 起点:左上角 path.move(to: CGPoint(x: 0, y: 0)) // 左边缘直线到左弧形起点 path.addLine(to: CGPoint(x: leftNotchEndX - notchHeight, y: 0)) // 左弧形:从顶部过渡到刘海底部 path.addCurve(to: CGPoint(x: leftNotchEndX, y: notchHeight), controlPoint1: CGPoint(x: leftNotchEndX - 8, y: 0), controlPoint2: CGPoint(x: leftNotchEndX - 4, y: notchHeight)) // 中间水平直线段 path.addLine(to: CGPoint(x: rightNotchStartX, y: notchHeight)) // 右弧形:从刘海底部过渡回顶部 path.addCurve(to: CGPoint(x: rightNotchStartX + notchHeight, y: 0), controlPoint1: CGPoint(x: rightNotchStartX + 4, y: notchHeight), controlPoint2: CGPoint(x: rightNotchStartX + 8, y: 0)) // 右边缘直线到右上角 path.addLine(to: CGPoint(x: viewWidth, y: 0)) // 右侧垂直直线到右下角 path.addLine(to: CGPoint(x: viewWidth, y: bounds.height)) // 底部水平直线到左下角 path.addLine(to: CGPoint(x: 0, y: bounds.height)) // 闭合路径 path.close() return path.cgPath } }
关键改动说明
- 动态控制中间宽度:新增
notchWidth属性,修改该值会自动重绘视图,可根据内容尺寸动态设置(比如根据内部label的宽度调整) - 路径重构:将原有的双弧形路径拆分为「左直线→左弧形→中间直线→右弧形→右直线」的结构,完美匹配期望的刘海形状
- 适配视图尺寸变化:重写
layoutSubviews方法,在视图宽高变化时自动重绘路径,保证布局适配 - 优化弧形控制点:调整曲线的控制点坐标,让弧形过渡更自然平滑,贴近真实iPhone刘海的弧度
内容的提问来源于stack exchange,提问作者Daniyal irfan
相关产品推荐
相关产品推荐

