swiftuiviewuikitcagradientlayer

CAGradientLayer edges pixelate after rotation


So I'm basically trying to create a rotated view with a gradient layer, but the edges seem to be quite pixelated after transforming (aka rotating) the view. As soon as I comment out rotation line, everything seems to be working just fine.

Any insight of what I'm doing wrong/ could do to fix that would be very appreciated.

GradientView class:

import UIKit.UIView

class GradientView: UIView {
    
    // MARK: Layers
    lazy var gradientLayer: CAGradientLayer = {
        let l = CAGradientLayer()
        l.frame = self.bounds
        l.cornerRadius = 10
        l.colors = [UIColor.red.cgColor,
                    UIColor.orange.cgColor,
                    UIColor.yellow.cgColor]
        layer.insertSublayer(l, at: 0)
        return l
    }()
    
    // MARK: Lifecycle
    override func layoutSubviews() {
        super.layoutSubviews()
        gradientLayer.frame = bounds
    }
    
    // MARK: Init
    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    // MARK: Helpers
    private func commonInit() {
        clipsToBounds = true
        backgroundColor = .clear
        layer.masksToBounds = true
    }
}

ViewController:

import UIKit

class ViewController: UIViewController {
    
    // MARK: Subviews
    private let gradientView = GradientView()
    
    // MARK: Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        configureSubviews()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        rotateView()
    }
    
    // MARK: Helpers
    private func configureSubviews() {
        configureGradientview()
        setLayout()
    }
    
    private func configureGradientview() {
        view.addSubview(gradientView)
        gradientView.translatesAutoresizingMaskIntoConstraints = false
    }
    
    private func setLayout() {
        NSLayoutConstraint.activate([
            gradientView.centerXAnchor.constraint(
                equalTo: view.centerXAnchor
            ),
            gradientView.centerYAnchor.constraint(
                equalTo: view.centerYAnchor
            ),
            gradientView.widthAnchor.constraint(
                equalTo: view.widthAnchor,
                multiplier: 0.8
            ),
            gradientView.heightAnchor.constraint(
                equalTo: gradientView.widthAnchor,
                multiplier: 0.4
            )
        ])
    }
    
    private func rotateView() {
        let angleInDegrees = 10.0
        let angleInRadians = CGFloat(angleInDegrees * .pi / 180)
        gradientView.transform = CGAffineTransform(
            rotationAngle: angleInRadians
        )
    }
}

Current result:

enter image description here


Solution

  • As per OP's comments...

    To solve the "jagged edges" we need to enable antialiasing on the "root layer" of the view:

    gradientView.layer.allowsEdgeAntialiasing = true
    

    As a side note, this doesn't have anything to do with the Gradient Layer --- we can see the same issue with a plain UIView.