Search code examples
iosswiftuiviewcore-graphics

How to control shadow spread and blur?


I have designed UI elements in sketch, and one of them has a shadow with blur 1 and spread 0. I looked at the doc for the views layer property and layer doesn't have anything named spread or blur, or anything equivalent (the only control was merely shadowOpacity). How can control things like blur and spread?

Here are my settings in Sketch:

Sketch shadow settings

And here is what I want my shadow to look like:

Shadow wanted

And here is what it looks like at the moment:

Current shadow

Note, you have to click on the picture to actually see the shadow.

My code is as follows:

func setupLayer(){
    view.layer.cornerRadius = 2
    view.layer.shadowColor = Colors.Shadow.CGColor
    view.layer.shadowOffset = CGSize(width: 0, height: 1)
    view.layer.shadowOpacity = 0.9
    view.layer.shadowRadius = 5
}

Solution

  • Here's how to apply all 6 Sketch shadow properties to a UIView's layer with near perfect accuracy:

    extension CALayer {
      func applySketchShadow(
        color: UIColor = .black,
        alpha: Float = 0.5,
        x: CGFloat = 0,
        y: CGFloat = 2,
        blur: CGFloat = 4,
        spread: CGFloat = 0)
      {
        masksToBounds = false
        shadowColor = color.cgColor
        shadowOpacity = alpha
        shadowOffset = CGSize(width: x, height: y)
        shadowRadius = blur / 2.0
        if spread == 0 {
          shadowPath = nil
        } else {
          let dx = -spread
          let rect = bounds.insetBy(dx: dx, dy: dx)
          shadowPath = UIBezierPath(rect: rect).cgPath
        }
      }
    }
    

    Say we want to represent the following:

    enter image description here

    You can easily do this via:

    myView.layer.applySketchShadow(
      color: .black, 
      alpha: 0.5, 
      x: 0, 
      y: 0, 
      blur: 4, 
      spread: 0)
    

    or more succinctly:

    myView.layer.applySketchShadow(y: 0)
    

    Example:

    enter image description here

    Left: iPhone 8 UIView screenshot; right: Sketch rectangle.

    Note:

    • When using a non-zero spread, it hardcodes a path based on the bounds of the CALayer. If the layer's bounds ever change, you'd want to call the applySketchShadow() method again.