UIView 子层中 CAShapelayer 的位置错误

Posted

技术标签:

【中文标题】UIView 子层中 CAShapelayer 的位置错误【英文标题】:Wrong position of CAShapelayer in sublayers of UIView 【发布时间】:2017-10-03 13:55:21 【问题描述】:

我正在尝试绘制:UIView 中间的 O-O-O 但得到:

这是一个计算 CAShapeLayer.frame 位置的函数。偶数索引是点,奇数索引是线。行数总是减去一个点数。

func frameForShape(at index: Int) -> CGRect 
    let dotWidth = dotRadius * 2
    let lineWidth = (view.bounds.width - (CGFloat(numberOfDots) * dotWidth)) / CGFloat(numberOfLines)

    if index % 2 == 0 
        let count = CGFloat(index) / 2
        let x = (lineWidth * count) + (dotWidth * count)
        return CGRect(x: x, y: 0, width: dotWidth, height: view.bounds.height)
     else 
        let count = Double(index) / 2
        let x = (lineWidth * CGFloat(floor(count))) + (dotWidth * CGFloat(ceil(count)))
        return CGRect(x: x, y: 0, width: lineWidth, height: view.bounds.height)
    


func setFrame() 
    for (index, shape) in shapes.enumerated() 
        shape.frame = frameForShape(at: index)
    

frameForShape(at:) 正确返回帧位置和大小

这个函数在给定框架的中心绘制一条路径

func linePath(rect: CGRect) -> UIBezierPath 
    let newRect = CGRect(x: rect.minX, y: rect.midY - (lineHeight / 2), width: rect.width, height: lineHeight)
    let path = UIBezierPath(rect: newRect)
    return path


func dotPath(rect: CGRect) -> UIBezierPath 
    let newRect = CGRect(x: rect.midX - dotRadius, y: rect.midY - dotRadius, width: dotRadius * 2, height: dotRadius * 2)
    let path = UIBezierPath(ovalIn: newRect)
    return path

在这里,我将 CAShapeLayers 添加到黄色 UIView

override func awakeFromNib() 
    super.awakeFromNib()

    for shape in shapes 
        view.layer.addSublayer(shape)
    


override func layoutSubviews() 
    super.layoutSubviews()
    layoutIfNeeded()

    setFrame()
    build()


func build() 
    for (index, shape) in shapes.enumerated() 
        if index % 2 == 0 
            shape.path = dotPath(rect: shape.frame).cgPath
         else 
            shape.path = linePath(rect: shape.frame).cgPath
        
    

框架是正确的,为什么点和线错位了?

我找到了这个答案:https://***.com/a/40194019/

图层位置不正确 - 框架应等于 parentView 中父图层的边界

但是如果 UIBezierPath(ovalIn:) 和 UIBezierPath(rect:) 都在框架内绘制,如何在特定位置绘制路径?

【问题讨论】:

正如答案所说,在调用 build() 时,将 shape.frame 更改为 shape.bounds。 @Sparky 它有效。请发布答案,以便我接受。 【参考方案1】:

正如答案所说,只需在调用 build() 时将 shape.frame 更改为 shape.bounds。

请记住,形状层的坐标是相对于包含视图的,因此需要使用边界。

【讨论】:

以上是关于UIView 子层中 CAShapelayer 的位置错误的主要内容,如果未能解决你的问题,请参考以下文章

检测旋转 CAShapeLayer 上的触摸

将 CAShapeLayer 添加到 UIButton 不起作用

使用 CALayer 的 UIView 没有出现阴影

具有弹簧效果的旋转动画

如何将子层与 UIView 一起移动?

带有 CAShapeLayer 的 UIView 不显示 CAGradientLayer