【问题标题】:Can CAShapeLayer shapes center itself in a subView?CAShapeLayer 形状可以在子视图中居中吗?
【发布时间】:2018-09-08 07:09:23
【问题描述】:

我创建了一个任意视图

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 时,圆圈远离视图的底部。可以在子视图的中心设置位置吗?

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】:

    你有两个问题。

    首先,您正在设置shapeLayer.position = middleView.center。视图的center 是父视图的几何图形。换句话说,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 中,从情节提要加载的视图仍然具有情节提要中给出的帧,并且尚未针对当前设备的屏幕尺寸进行布局。因此,如果您不采取措施确保在布局阶段正确布局,那么查看viewDidLoad 中的frame(或boundscenter)是一个坏主意。通常您通过设置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或者约束来控制shape的布局,可以在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
        }
    
    }
    

    结果:

    旋转到横向后:

    【讨论】:

    • 谢谢!这是非常有见地的。一问:我可以将circleView.autoresizingMask = [...] 换成自动布局约束吗?他们执行相同的任务吗?
    • 是的,如果你记得设置circleVIew.translatesAutoresizingMaskIntoConstraints = false,你可以使用约束来布局circleView
    • 我猜,我很困惑CGRect.xCGRect.y 中的0 是如何让圆圈居中的
    • 那些无关紧要,因为我在下一行设置了circleView.center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 2017-07-21
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多