无法将围绕 imageView 的圆形图层放在不同的 iPhone 设备上

Can't put circular layer that surrounds imageView on different iPhone devices

我该如何解决这个问题? 图像在故事板中设置了约束;另一个圆圈是用这些代码行设置的:

let centerY = profileImage.center.y+20+(self.navigationController?.navigationBar.frame.size.height)!
let centerX = profileImage.center.x
let center = CGPoint(x: centerX, y: centerY)
let trackLayer = CAShapeLayer()
let circularPath = UIBezierPath(arcCenter: center, radius: (profileImage.frame.width/2)+2, startAngle: -CGFloat.pi-CGFloat.pi/2, endAngle: CGFloat.pi/2, clockwise: true)
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = Functions.hexStringToUIColor(hex: "#3859B9").cgColor
trackLayer.lineWidth = 3
trackLayer.lineCap = kCALineCapRound
trackLayer.fillColor = UIColor.clear.cgColor
view.layer.addSublayer(trackLayer)

上iPhone7(右边那个)好像是对的。

对导航栏或状态栏的高度使用固定值会导致此类错误。您应该根据图像视图定位图层。为此,您可以简单地将图像视图的框架分配给您的图层:

trackLayer.frame = profileImage.frame

由于布局可能会因多种原因而改变(例如设备旋转),您应该在视图控制器的 viewDidLayoutSubviews 中执行此操作。

由于图层的框架现在比您的示例中的要小,因此您应该使用以下方法创建中心:

let center = CGPoint(x: profileImage.bounds.midX, y: profileImage.bounds.midY)
override func viewDidLayoutSubviews() {

    let centerY = profileImage.center.y+20+(self.navigationController?.navigationBar.frame.size.height)!
    let centerX = profileImage.center.x
    let center = CGPoint(x: centerX, y: centerY)
    let trackLayer = CAShapeLayer()
    let circularPath = UIBezierPath(arcCenter: center, radius: (profileImage.frame.width/2)+2, startAngle: -CGFloat.pi-CGFloat.pi/2, endAngle: CGFloat.pi/2, clockwise: true)
    trackLayer.path = circularPath.cgPath
    trackLayer.strokeColor = Functions.hexStringToUIColor(hex: "#3859B9").cgColor
    trackLayer.lineWidth = 3
    trackLayer.lineCap = kCALineCapRound
    trackLayer.fillColor = UIColor.clear.cgColor
    view.layer.addSublayer(trackLayer)

 }

或者直接在 viewDidAppear 中编写代码

这将解决问题。

  1. layer 添加到 profileImage.layer
  2. trackLayer.frame = profileImage.bounds

完整代码应该是这样的:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let center = CGPoint(x: profileImage.bounds.midX,
                         y: profileImage.bounds.midY)
    let trackLayer = CAShapeLayer()
    trackLayer.frame = profileImage.frame
    let circularPath = UIBezierPath(arcCenter: center,
                                    radius: (profileImage.frame.width / 2) + 2,
                                    startAngle: -CGFloat.pi - CGFloat.pi / 2,
                                    endAngle: CGFloat.pi / 2, clockwise: true)
    trackLayer.path = circularPath.cgPath
    trackLayer.strokeColor = Functions.hexStringToUIColor(hex: "#3859B9").cgColor
    trackLayer.lineWidth = 3
    trackLayer.lineCap = kCALineCapRound
    trackLayer.fillColor = UIColor.clear.cgColor
    profileImage.layer.addSublayer(trackLayer)
}

使用界面生成器:

  1. 将 UIView 拖放到图像视图上方
  2. 将视图自定义 class 更改为 CirculerProgressView
  3. 使用图像视图中心设置中心 X 和 Y 约束
  4. 设置高度和宽度限制(大于 imageView 高度和宽度)

    @IBDesignable class CirculerProgressView: UIView {
    
                override class var layerClass: AnyClass {
                    return CAShapeLayer.self
                }
    
                override func draw(_ rect: CGRect) {
                    super.draw(rect)
                    setupLayer()
                }
    
                private func setupLayer() {
                    let trackLayer = layer as! CAShapeLayer
                    let center = CGPoint(x: frame.width/2, y: frame.height/2)
                    let circularPath = UIBezierPath(arcCenter: center, radius: frame.width/2, startAngle: -CGFloat.pi-CGFloat.pi/2, endAngle: CGFloat.pi/2, clockwise: true)
                    trackLayer.path = circularPath.cgPath
                    trackLayer.strokeColor = UIColor.blue.cgColor
                    trackLayer.lineWidth = 3
                    trackLayer.lineCap = kCALineCapRound
                    trackLayer.fillColor = UIColor.clear.cgColor
                }}