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

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
    }
}

关键改动说明

  1. 动态控制中间宽度:新增notchWidth属性,修改该值会自动重绘视图,可根据内容尺寸动态设置(比如根据内部label的宽度调整)
  2. 路径重构:将原有的双弧形路径拆分为「左直线→左弧形→中间直线→右弧形→右直线」的结构,完美匹配期望的刘海形状
  3. 适配视图尺寸变化:重写layoutSubviews方法,在视图宽高变化时自动重绘路径,保证布局适配
  4. 优化弧形控制点:调整曲线的控制点坐标,让弧形过渡更自然平滑,贴近真实iPhone刘海的弧度

内容的提问来源于stack exchange,提问作者Daniyal irfan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:38:11