【问题标题】:Autorotation of CALayer on iPhone rotationiPhone旋转时CALayer的自动旋转
【发布时间】:2009-08-15 16:50:01
【问题描述】:

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

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

当我旋转设备时,视图会旋转,但 CALayer 不会。它有点被分流到左边,仍然是纵向视图。

有没有办法让子图层自动旋转,还是我需要应用变换?

【问题讨论】:

    标签: ios cocoa-touch core-animation calayer


    【解决方案1】:

    使用 Swift 4 / iOS 11,根据您的需要,您可以选择 以下 6 个示例之一,以便在设备旋转时管理您的 CALayer / CAGradientLayer 框架。

    以下示例使用CAGradientLayer,但可以轻松映射到CALayerCAShapeLayer 案例。


    #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。使用键值观察 (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
        }
    
    }
    

    来源:

    【讨论】:

    • 你的代码中有一些错误……如果你重写了一个函数,你首先要做的是什么? … 打电话给超级
    【解决方案2】:

    您需要自己管理 CALayer 的旋转。我相信 0,0 会保持在同一个位置,并且会更改大小以匹配新方向,因此如果您想自己做某事,则需要自己管理旋转变换的添加。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-07
      • 1970-01-01
      • 2011-05-11
      • 2011-09-24
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      相关资源
      最近更新 更多