Search code examples
iosswiftuiviewcashapelayer

Center of UIView not centered


I have a CAShapeLayer that I am adding to the center of a UIView, but instead of appearing in the center, it appears in the top left corner of the UIView.

Here's the view setup:

let trayProgress: UIView = {
    let view = UIView()
    view.backgroundColor = .yellow

    let trackLayer = CAShapeLayer()
    let circularPath = UIBezierPath(arcCenter: view.center, radius: 20, startAngle: -CGFloat.pi / 2, endAngle: CGFloat.pi * 2, clockwise: false)
    trackLayer.path = circularPath.cgPath
    trackLayer.strokeColor = UIColor.lightGray.cgColor
    trackLayer.lineWidth = 6
    trackLayer.fillColor = UIColor.clear.cgColor
    view.layer.addSublayer(trackLayer)

    return view
}()

Here's what is showing in the view (I expect the gray circle to be in the center of the yellow view):

output

I have also tried to replace view.center with CGPoint(x: view.center.x, y: view.center.y), but I get the same result.

Can anyone tell me why this is happening and how I can fix it? Thanks!


Solution

  • The problem is in part this line:

    arcCenter: view.center
    

    That makes no sense, because the view’s center is where it is in its superview. You want to make the shape layer’s frame the same as the view’s bounds! The arc center should then be the shape layer’s own center (which, because it is a layer, is its position).

    But another part of the problem is that in the code you’ve shown neither the view nor the shape layer has any size. You cannot create the shape layer until the view has size.

    Example (I have starred the key changes in the code):

    let trayProgress: UIView = {
        let view = UIView(frame:CGRect(x: 30, y: 60, width: 50, height: 50)) // *
        view.backgroundColor = .yellow
        let trackLayer = CAShapeLayer()
        trackLayer.frame = view.bounds // *
        let circularPath = UIBezierPath(arcCenter: trackLayer.position, // *
            radius: 20, startAngle: -CGFloat.pi / 2, endAngle: CGFloat.pi * 2, clockwise: false)
        trackLayer.path = circularPath.cgPath
        trackLayer.strokeColor = UIColor.lightGray.cgColor
        trackLayer.lineWidth = 6
        trackLayer.fillColor = UIColor.clear.cgColor
        view.layer.addSublayer(trackLayer)
        return view
    }()
    

    Result:

    enter image description here

    You can tweak that, of course. For example you can move the center of the view to wherever you like.