iPhone旋转时CALayer的自动旋转

3

我有一个UIViewController,在其中我将一个CALayer子类添加到视图的layer中:

[self.view.layer addSublayer:myObject.backgroundLayer];

当我旋转设备时,视图会旋转,但CALayer却没有旋转。它似乎被推到了左边,仍然保持竖屏视图。
有没有办法让子层自动旋转或者我需要应用一个变换?
2个回答

4
使用Swift 4 / iOS 11,根据您的需求,您可以选择以下6个示例之一来管理设备旋转时的CALayer / CAGradientLayer框架。
以下示例使用CAGradientLayer,但可以轻松映射到CALayer或CAShapeLayer情况。
#1.覆盖UIViewController viewDidLayoutSubviews()。
import UIKit

class ViewController: UIViewController {

    let gradientLayer: CAGradientLayer = {
        let layer = CAGradientLayer()
        layer.colors = [
            UIColor.blue.cgColor,
            UIColor.cyan.cgColor
        ]
        return layer
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.layer.addSublayer(gradientLayer)
        gradientLayer.frame = view.bounds
    }

    override func viewDidLayoutSubviews() {         
        gradientLayer.frame = view.bounds
    }

}

#2. 覆盖UIViewControllerloadView()方法,子类化UIView并覆盖UIViewlayoutSubviews()方法

LayerView.swift

import UIKit

class LayerView: UIView {

    lazy var gradientLayer: CAGradientLayer = {
        let layer = CAGradientLayer()
        layer.colors = [
            UIColor.blue.cgColor,
            UIColor.cyan.cgColor
        ]
        self.layer.addSublayer(layer)
        return layer
    }()

    override func layoutSubviews() {
        gradientLayer.frame = bounds
    }

}

LayerView.swift(替代方案)

import UIKit

class LayerView: UIView {

    var gradientLayer: CAGradientLayer!

    override func layoutSubviews() {
        if gradientLayer == nil {
            let gradientLayer = CAGradientLayer()
            gradientLayer.colors = [
                UIColor.blue.cgColor,
                UIColor.cyan.cgColor
            ]
            self.gradientLayer = gradientLayer
            layer.addSublayer(gradientLayer)
        }

        gradientLayer.frame = bounds
    }

}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    let layerView = LayerView()

    override func loadView() {
        view = layerView
    }

}

#3. Using Key Value Observing (KVO)

import UIKit

class ViewController: UIViewController {

    var observation: NSKeyValueObservation?

    let gradientLayer: CAGradientLayer = {
        let layer = CAGradientLayer()
        layer.colors = [
            UIColor.blue.cgColor,
            UIColor.cyan.cgColor
        ]
        return layer
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.layer.addSublayer(gradientLayer)

        observation = view.observe(\.frame, options: [.new], changeHandler: { [unowned self] (object: UIView, change: NSKeyValueObservedChange<CGRect>) in
            guard let frame = change.newValue else { return }
            self.gradientLayer.frame = frame
        })

        // Also works
        /*
        observation = observe(\.view.frame, options: [.new], changeHandler: { [unowned self] (object: ViewController, change: NSKeyValueObservedChange<CGRect>) in
            guard let frame = change.newValue else { return }
            self.gradientLayer.frame = frame
        })
        */
    }

}

#4. 覆盖UIViewControllerloadView()方法,子类化UIView并覆盖UIViewlayerClass方法

LayerView.swift

import UIKit

class LayerView: UIView {

    override public class var layerClass: AnyClass {
        return CAGradientLayer.self
    }

    required init() {
        super.init(frame: .zero)

        guard let gradientLayer = layer as? CAGradientLayer else { return }
        gradientLayer.colors = [
            UIColor.blue.cgColor,
            UIColor.cyan.cgColor
        ]
    }

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

}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    let layerView = LayerView()

    override func loadView() {
        view = layerView
    }

}

#5. 覆盖UIViewControllerloadView()、子类化UIView并覆盖CALayerDelegatelayoutSublayers(of:)

LayerView.swift

import UIKit

class LayerView: UIView {

    required init() {
        super.init(frame: .zero)

        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [
            UIColor.blue.cgColor,
            UIColor.cyan.cgColor
        ]

        layer.addSublayer(gradientLayer)
    }

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

    override func layoutSublayers(of layer: CALayer) {
        layer.sublayers?.forEach {
            $0.frame = layer.bounds
        }
    }

}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    let layerView = LayerView()

    override func loadView() {
        view = layerView
    }

}

#6. 重写 UIViewControllerloadView() 方法,继承 UIView 并重写 UIViewlayerClass 方法,继承 CALayer 并重写 CALayerlayoutSublayers() 方法。

Layer.swift

import UIKit

class Layer: CALayer {

    override init() {
        super.init()

        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [
            UIColor.blue.cgColor,
            UIColor.cyan.cgColor
        ]

        addSublayer(gradientLayer)
    }

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

    override func layoutSublayers() {
        sublayers?.forEach {
            $0.frame = bounds
        }
    }

}

LayerView.swift

import UIKit

class LayerView: UIView {

    override public class var layerClass: AnyClass {
        return Layer.self
    }

}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    let layerView = LayerView()

    override func loadView() {
        view = layerView
    }

}

Sources:


你的代码有一些错误...如果你要重写一个函数,第一件事情是什么?...调用super。 - StackUnderflow

0

您需要自己管理CALayer的旋转。我相信0,0保持在原位,大小会根据新方向进行更改,因此如果您想要自己做一些事情,您需要自己管理旋转变换的添加。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接