在 UIView 中居中 CAShapeLayer?

Centering a CAShapeLayer within a UIView?

像这道题大概有 5 个以上,但其中 none 个解决了问题。

我想在一个视图上以一个圆为中心。尽管通过类似的问题尝试了各种方法,但它并没有发生。

我不确定是否会发生这种情况,因为我设置了 translatesAutoresizingMaskIntoConstraints = false。我试着玩弄形状层的中心点和锚点,但疯狂的行为发生了。我试着把这段代码放在 viewDidLayouSubviews 中。没用。我还能做什么?

colorSizeGuide 是我试图将图层居中的视图。

func setupConstraints() {
    // other constraints set up here
    colorSizeGuide.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    colorSizeGuide.topAnchor.constraint(equalTo: view.topAnchor, constant: 30).isActive = true
    colorSizeGuide.widthAnchor.constraint(equalToConstant: 30).isActive = true
    colorSizeGuide.heightAnchor.constraint(equalToConstant: 30).isActive = true
}

func setupColorSizeGuide() {
    shape.path = UIBezierPath(ovalIn: colorSizeGuide.frame).cgPath
    shape.position = self.colorSizeGuide.center
    shape.anchorPoint = CGPoint(x: 0.5, y: 0.5)

    shape.strokeColor = (UIColor.black).cgColor
    shape.fillColor = (UIColor.clear).cgColor
    shape.lineWidth = 1.0
    colorSizeGuide.layer.addSublayer(shape)

} 

您可以选择几个选项。

  1. 如果您不在滚动环境中(例如 tableView),请在视图上使用矩形宽度一半的角半径,然后视图将被裁剪为圆形 - 这不是特别快或可定制,但它完成了工作。

游乐场代码:

import UIKit
import PlaygroundSupport

let frame: CGRect = CGRect(x: 0, y: 0, width: 100, height: 100)
let view: UIView = UIView(frame: frame)
view.backgroundColor = .magenta
view.layer.cornerRadius = frame.size.width / 2
PlaygroundPage.current.liveView = view
  1. 您可以让您的自定义 UIView 子类在其中实现 layerClass 方法和 return CAShapeLayer。这意味着您视图的 self.layer 实际上是一个形状图层。您可以在那里设置一个圆圈的路径,然后就可以了。如果你想让它在视图中居中,只需确保在定义 UIBezierPath.
  2. 时使用视图的边界坐标

游乐场代码:

import UIKit
import PlaygroundSupport

let frame: CGRect = CGRect(x: 0, y: 0, width: 100, height: 100)
let view: UIView = UIView(frame: frame)
PlaygroundPage.current.liveView = view

class ShapeView: UIView {

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

    override init(frame: CGRect) {
        super.init(frame: frame)
        (layer as? CAShapeLayer)?.fillColor = UIColor.red.cgColor
        (layer as? CAShapeLayer)?.strokeColor = UIColor.green.cgColor
        (layer as? CAShapeLayer)?.path = UIBezierPath(ovalIn: frame).cgPath
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

let sv = ShapeView(frame: frame)
view.addSubview(sv)
  1. 通过执行 CAShapeLayer.init 创建一个非视图形状图层。将你的视图放在它的 layoutSubviews 方法中(如果你在视图控制器中这样做,则为 viewDidLayoutSubviews )并为形状层设置一个合适的框架,就像它是一个视图一样。

游乐场代码:

import UIKit
import PlaygroundSupport

let frame: CGRect = CGRect(x: 0, y: 0, width: 100, height: 100)
let smallFrame: CGRect = CGRect(x: 0, y: 0, width: 10, height: 10)
let view: UIView = UIView(frame: frame)
view.backgroundColor = .magenta
PlaygroundPage.current.liveView = view



let sl = CAShapeLayer()
sl.path = UIBezierPath(ovalIn: smallFrame).cgPath
sl.fillColor = UIColor.red.cgColor
sl.strokeColor = UIColor.green.cgColor

sl.frame.origin.x = 30
sl.frame.origin.y = 30

view.layer.addSublayer(sl)