ios - 动画边界更改时具有 CALayer 有线效果的自定义 View

标签 ios animation uiview calayer

我通过添加 CALayer 作为 UIView 的子层来实现自定义 View 。当我使用以下内容对 View 进行动画处理时:UIView.animateWithDuration(2.0) { self.slider.bounds.size *= 2.0} ,缩放动画有点错误。 CALayer 从缩放尺寸的错误位置开始,并移动到最终位置,而不是随 View 缩放。

CustomeView 代码:

import UIKit

class GridMaskView: UIView {
    private let cornerLayer: CAShapeLayer
    private let borderLayer: CAShapeLayer
    private let gridLayer: CAShapeLayer

    private let gridSize: (horizontal: UInt, vertical: UInt) = (3, 3)
    private let cornerThickness: CGFloat = 3.0
    private let cornerLength: CGFloat = 20.0
    private let borderThickness: CGFloat = 2.0
    private let gridThickness: CGFloat = 1.0
    private let lineColor: UIColor = UIColor(r: 120, g: 179, b: 193, a: 1)

    var showGridLines: Bool = true {
        didSet {
            gridLayer.hidden = !showGridLines
        }
    }

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

    override init(frame: CGRect) {
        cornerLayer = CAShapeLayer()
        cornerLayer.fillColor = lineColor.CGColor

        borderLayer = CAShapeLayer()
        borderLayer.fillColor = UIColor.clearColor().CGColor
        borderLayer.strokeColor = lineColor.CGColor
        borderLayer.lineWidth = borderThickness

        gridLayer = CAShapeLayer()
        gridLayer.strokeColor = lineColor.CGColor
        gridLayer.lineWidth = gridThickness

        super.init(frame: frame)
        layer.addSublayer(cornerLayer)
        layer.addSublayer(borderLayer)
        layer.addSublayer(gridLayer)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        layoutLayers()
    }

    private func layoutLayers() {
        drawCorner()
        drawBorder()
        drawGrid()
    }

    private func drawCorner() {
        cornerLayer.frame = bounds.insetBy(dx: -cornerThickness, dy: -cornerThickness)
        cornerLayer.path = cornerPath(forBounds: cornerLayer.bounds)
    }

    private func cornerPath(forBounds bounds: CGRect) -> CGPathRef {
        let horizontalSize = CGSize(width: cornerLength, height: cornerThickness)
        let verticalSize = CGSize(width: cornerThickness, height: cornerLength)

        let corners: [(CGRectEdge, CGRectEdge)] = [(.MinXEdge, .MinYEdge), (.MinXEdge, .MaxYEdge), (.MaxXEdge, .MinYEdge), (.MaxXEdge, .MaxYEdge)]

        var cornerRects = [CGRect]()
        for corner in corners {
            cornerRects.append(bounds.align(horizontalSize, corner: corner.0, corner.1))
            cornerRects.append(bounds.align(verticalSize, corner: corner.0, corner.1))
        }

        let cornerPath = CGPathCreateMutable()
        CGPathAddRects(cornerPath, nil, cornerRects, cornerRects.count)

        return cornerPath
    }

    private func drawBorder() {
        borderLayer.frame = bounds
        borderLayer.path = borderPath(forBounds: borderLayer.bounds)
    }

    private func borderPath(forBounds bounds: CGRect) -> CGPathRef {
        let borderPath = CGPathCreateMutable()
        let borderCornerPoints = [bounds.topLeft, bounds.topRight, bounds.bottomRight, bounds.bottomLeft, bounds.topLeft]
        CGPathAddLines(borderPath, nil, borderCornerPoints, borderCornerPoints.count)

        return borderPath
    }

    private func drawGrid() {
        gridLayer.frame = bounds
        gridLayer.path = gridPath(forBounds: gridLayer.bounds)
    }

    private func gridPath(forBounds bounds: CGRect) -> CGPathRef {
        let stepSize = bounds.size / (CGFloat(gridSize.horizontal), CGFloat(gridSize.vertical))

        let gridPath = CGPathCreateMutable()
        for i in (1...gridSize.vertical) {
            let x = CGFloat(i) * stepSize.width
            CGPathMoveToPoint(gridPath, nil, x, 0)
            CGPathAddLineToPoint(gridPath, nil, x, bounds.size.height)
        }

        for i in (1...gridSize.horizontal) {
            let y = CGFloat(i) * stepSize.height
            CGPathMoveToPoint(gridPath, nil, 0, y)
            CGPathAddLineToPoint(gridPath, nil, bounds.size.width, y)
        }
        return gridPath
    }

    override func intrinsicContentSize() -> CGSize {
        return CGSize(width: cornerLength * 2, height: cornerLength * 2)
    }
}

有人知道怎么装吗?

最佳答案

问题是,当您查看动画时,您不会获得任何子图层的自动动画。您最好使用原始 UIView 的 subview ,因为 View 动画将根据其自动布局约束将其与原始 View 一起制作动画。

关于ios - 动画边界更改时具有 CALayer 有线效果的自定义 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46587628/

相关文章:

iOS iPod API - 获取实际的歌曲文件

iphone - 如何在 iOS 中暂时隐藏 GADBannerView?

ios - swift - 弹出窗口在横向模式下显示不正确

java - 如何制作动画Activity过渡

ios - 如何在 iOS 中制作带有底部箭头的提示气球?

ios - 如果禁用 UITextField(在相应的 UIView 中),更改 UILabel 的颜色? ( swift )

iphone - UIScrollView背后如何与UIView交互

ios - xCode 在运行应用程序时失去与设备的连接

java - 如何为每个 ListView 项目制作翻译动画

python - 使用 matplotlib 转换多边形的动画