Search code examples
iosswiftxcodecalayershadow

Cannot layout CALayer frame correctly


I'm trying to set the frame of some CALayers but when I run this code they appear shifted to the right.

The frame coordinates and the shadows are correct. I use this class as a UIView class from a view in storyboard.

class Shadows: UIView {

    let darkShadow = CALayer()
    let lightShadow = CALayer()

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    override func layoutSublayers(of layer: CALayer) {
        super.layoutSublayers(of: layer)
        shadows()
    }

    private func shadows() {
        let cornerRadius: CGFloat = 30
        let shadowRadius: CGFloat = 8

        layer.cornerRadius = cornerRadius
        layer.masksToBounds = false

        darkShadow.frame = frame
        darkShadow.backgroundColor = UIColor.white.cgColor
        darkShadow.shadowColor = UIColor.black.cgColor
        darkShadow.cornerRadius = cornerRadius
        darkShadow.shadowOffset = CGSize(width: shadowRadius, height: shadowRadius)
        darkShadow.shadowOpacity = 0.2
        darkShadow.shadowRadius = shadowRadius
        layer.insertSublayer(darkShadow, at: 0)

        lightShadow.frame = frame
        lightShadow.backgroundColor = UIColor.white.cgColor
        lightShadow.shadowColor = UIColor.white.cgColor
        lightShadow.cornerRadius = cornerRadius
        lightShadow.shadowOffset = CGSize(width: -shadowRadius, height: -shadowRadius)
        lightShadow.shadowOpacity = 0.7
        lightShadow.shadowRadius = shadowRadius
        layer.insertSublayer(lightShadow, at: 0)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}

Solution

  • Here is the simple fix for your issue provide the bounds instead of the frame as the frame for the CALayer, here's how:

    darkShadow.frame = bounds
    

    To understand how this works you need to know the basics of UIKit layout and the difference between frame and bounds (You might wanna google this). In simple words, frame is the coordinates of the view with respect to super and bounds is with respect to itself.

    Note: (I'm adding this here just as a guideline) It's a common beginner mistake. There are plenty of online resources that explain the difference between frame and bounds. Although you might find it a bit overwhelming in the beginning you will get to know the difference eventually. Here are the ones I found useful and could be helpful for you as well :- Youtube Video of Saun Alen and Article from hacking with swift.