CAShapeLayer可以在subView中塑造自己的中心吗?

问题描述 投票:0回答:1

我创建了一个任意视图

let middleView = UIView(
    frame: CGRect(x: 0.0,
                  y: view.frame.height/4,
                  width: view.frame.width,
                  height: view.frame.height/4))
middleView.backgroundColor = UIColor.blue
view.addSubview(middleView)

然后我用UIBezierPath创建了一个圆圈;但是当我将位置设置为middleView.center时,圆圈远离视图的底部。你能在子视图的中心设置位置吗?

iPhone 8 Plus with view and uncentered circle

let shapeLayer = CAShapeLayer()
let circlePath = UIBezierPath(
        arcCenter: .zero,
        radius: 100,
        startAngle: CGFloat(0).toRadians(),
        endAngle: CGFloat(360).toRadians(),
        clockwise: true)
shapeLayer.path = circlePath.cgPath
shapeLayer.strokeColor = UIColor.purple.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.position = middleView.center
middleView.layer.addSublayer(shapeLayer)

如何在该视图中居中此圆圈?

swift cashapelayer caanimation
1个回答
3
投票

你有两个问题。

首先,你要设置shapeLayer.position = middleView.center。视图的center是superview的几何。换句话说,middleView.center是相对于view,而不是middleView。但是你加入shapeLayer作为middleView.layer的子层,这意味着shapeLayer需要position几何中的middleView,而不是view的几何。你需要将shapeLayer.position设置为middleView.bounds的中心:

shapeLayer.position = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)

其次,你没有说你在做什么。我的猜测是你在viewDidLoad做的。但那太早了。在viewDidLoad中,从故事板加载的视图仍然具有在故事板中给出的帧,并且尚未针对当前设备的屏幕大小进行布局。因此,如果你没有采取措施确保在布局阶段正确布局,那么在frame中查看bounds(或centerviewDidLoad)是一个坏主意。通常通过设置autoresizingMask或创建约束来完成此操作。例:

let middleView = UIView(
    frame: CGRect(x: 0.0,
                  y: view.frame.height/4,
                  width: view.frame.width,
                  height: view.frame.height/4))
middleView.backgroundColor = UIColor.blue
middleView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin]
view.addSubview(middleView)

但是,shapeLayer不属于视图,所以它没有autoresizingMask并且不能被约束。你必须在代码中列出它。您可以这样做,但最好只使用视图来管理形状图层。这样,你可以使用autoresizingMask或约束来控制形状的布局,你可以在viewDidLoad中设置它。

    let circleView = CircleView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
    circleView.center = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
    circleView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
    circleView.shapeLayer.strokeColor = UIColor.purple.cgColor
    circleView.shapeLayer.fillColor = nil
    middleView.addSubview(circleView)

...

class CircleView: UIView {
    override class var layerClass: AnyClass { return CAShapeLayer.self }

    var shapeLayer: CAShapeLayer { return layer as! CAShapeLayer }

    override func layoutSubviews() {
        super.layoutSubviews()
        shapeLayer.path = UIBezierPath(ovalIn: bounds).cgPath
    }

}

结果:

demo

旋转到风景后:

demo in landscape

© www.soinside.com 2019 - 2024. All rights reserved.