CAGradientLayer 搞砸了 CATransform3DRotate

CAGradientLayer messes up CATransform3DRotate

我在 CATransform3DRotate 中观察到一个奇怪的行为,我正在将其应用到视图的图层,该视图位于图层具有 CAGradientLayer.

的视图前面

当存在渐变视图时,变换动画会掩盖我正在变换的视图的一半以及它前面的所有其他内容。如果渐变视图不存在或不在视图后面,一切都很好。

这里有截图来说明我的意思。您可以清楚地看到旋转视图是如何部分隐藏的,下面的滑块也是如此。

因为看起来渐变层在不同的 z-plane 上,所以我试了一下它的 z 位置,但这没有帮助。此外,这仍然无法向我解释完全不相关的 UISlider 是如何被掩盖的。

我做错了什么?

下面是一个完整的 self-contained UIViewController 说明了我的问题。

class TestViewController: UIViewController {
    private var gradientLayer: CAGradientLayer!
    private var flipContent: UILabel!
    private var flipView: UIView!
    private var gradientView: UIView!
    private var slider: UISlider!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        setupGradientLayer()
    }

    @IBAction func didChangeValue(_ sender: UISlider) {
        var perspectiveTransform = CATransform3DIdentity
        perspectiveTransform.m34 = -0.002
        let rotateAngle = CGFloat(sender.value) * CGFloat(Double.pi)
        let flipTransform = CATransform3DRotate(perspectiveTransform, rotateAngle, 0, 1, 0)
        flipView.layer.transform = flipTransform
    }

    private func setupGradientLayer() {
        gradientLayer = CAGradientLayer()
        gradientLayer.colors = [
            UIColor(red: 74 / 255, green: 173 / 255, blue: 255 / 255, alpha: 1.0).cgColor,
            UIColor(red: 0 / 255, green: 94 / 255, blue: 215 / 255, alpha: 1.0).cgColor
        ]
        gradientLayer.frame = view.bounds
        gradientView.layer.insertSublayer(gradientLayer, at: 0)
    }

    private func setupViews() {
        gradientView = UIView(frame: CGRect(x: 10, y: 150, width: 200, height: 30))
        slider = UISlider(frame: CGRect(x: 10, y: 400, width: 200, height: 30))
        slider.minimumValue = 0
        slider.maximumValue = 1
        slider.addTarget(self, action: #selector(didChangeValue(_:)), for: .valueChanged)
        flipView = UIView(frame: CGRect(x: 10, y: 100, width: 200, height: 200))
        flipView.backgroundColor = UIColor.lightGray
        flipContent = UILabel(frame: CGRect(x: 10, y: 100, width: 100, height: 100))
        flipContent.text = "I will flip"

        flipView.addSubview(flipContent)
        view.addSubview(gradientView)
        view.addSubview(flipView)
        view.addSubview(slider)
    }
}

为您的转换添加 z 翻译:

var perspectiveTransform = CATransform3DIdentity
perspectiveTransform.m34 = -0.002
let rotateAngle = CGFloat(sender.value) * CGFloat(Double.pi)
perspectiveTransform = CATransform3DTranslate(perspectiveTransform, 0, 0, 300)
flipView.layer.transform = CATransform3DRotate(perspectiveTransform, rotateAngle, 0, 1, 0)

如果您查看调试视图层次结构,您会发现您的视图在同一个计划中。

您还可以设置 zPosition(这是一种 shorthand 用于 z 平移):

flipView.layer.zPosition = 300