Search code examples
swiftuiimageviewcalayershadow

How do I cast two shadows from an UIImageView with a SF Symbol as the image?


I want to cast a shadow to the lower left AND the lower right of my Image. But I'm struggling to get the second shadow cast (layer2)...

enter image description here

I've created a subclass of UIImage view and use that in IB:

import UIKit

class ShadowImageView: UIImageView {

    var layer2 = CALayer()

    override func layoutSubviews() {
        super.layoutSubviews()

        self.layer2 = CALayer(layer: self.layer)

        self.clipsToBounds = false

        self.layer.shadowColor = UIColor.gray.cgColor
        self.layer.shadowOffset = CGSize(width: -16, height: 16)
        self.layer.shadowOpacity = 0.33
        self.layer.shadowRadius = 3
        self.layer.masksToBounds = false

        self.layer2.shadowColor = UIColor.gray.cgColor
        self.layer2.shadowOffset = CGSize(width: 16, height: 16)
        self.layer2.shadowOpacity = 0.33
        self.layer2.shadowRadius = 3
        self.layer2.masksToBounds = false

        self.layer.insertSublayer(self.layer2, at: 0)

        print("\(self.layer)\n")
        if let sublayers = self.layer.sublayers {
            for layer in sublayers {
                print("\(layer)\n")
            }
        }
    }
}

Am I going in the right direction to copy the layer and apply a new shadow to it or should I look in a different direction?


Solution

  • enter image description here

    Fixed the shadow problem. I was able to generate double shadows by adding 3 layers on my UIView. The furthest behind (the first sublayer of the view's layer) is the darker shadow, the one on top of that is the lighter shadow and on top of that I have one with the normal color.

    I'm 'drawing' the images on the layers by applying a shadow path & color.

    The image I'm drawing is coming from a method like listed below, but it's not being generated from a SFSymbols. I would like to generate it during runtime so I end up with a simple method of using symbols to place Neumorphic elements in our apps. The manual generation of these BezierPaths isn't really pleasant.

    static var shieldFill: UIBezierPath = {
        let bezierPath = UIBezierPath()
        bezierPath.move(to: CGPoint(x: 58.94, y: 115.53))
        bezierPath.addCurve(to: CGPoint(x: 62.84, y: 114.4), controlPoint1: CGPoint(x: 60.06, y: 115.53), controlPoint2: CGPoint(x: 61.57, y: 115.04))
        bezierPath.addCurve(to: CGPoint(x: 101.76, y: 74.46), controlPoint1: CGPoint(x: 91.5, y: 100.49), controlPoint2: CGPoint(x: 101.76, y: 91.89))
        bezierPath.addLine(to: CGPoint(x: 101.76, y: 39.94))
        bezierPath.addCurve(to: CGPoint(x: 92.04, y: 25.05), controlPoint1: CGPoint(x: 101.76, y: 31.84), controlPoint2: CGPoint(x: 99.41, y: 28.12))
        bezierPath.addCurve(to: CGPoint(x: 67.63, y: 16.85), controlPoint1: CGPoint(x: 87.89, y: 23.29), controlPoint2: CGPoint(x: 71.29, y: 17.97))
        bezierPath.addCurve(to: CGPoint(x: 58.94, y: 15.53), controlPoint1: CGPoint(x: 64.94, y: 16.11), controlPoint2: CGPoint(x: 61.52, y: 15.53))
        bezierPath.addCurve(to: CGPoint(x: 50.24, y: 16.85), controlPoint1: CGPoint(x: 56.35, y: 15.53), controlPoint2: CGPoint(x: 52.93, y: 16.11))
        bezierPath.addCurve(to: CGPoint(x: 25.83, y: 25.05), controlPoint1: CGPoint(x: 46.53, y: 17.97), controlPoint2: CGPoint(x: 29.93, y: 23.29))
        bezierPath.addCurve(to: CGPoint(x: 16.11, y: 39.94), controlPoint1: CGPoint(x: 18.46, y: 28.12), controlPoint2: CGPoint(x: 16.11, y: 31.84))
        bezierPath.addLine(to: CGPoint(x: 16.11, y: 74.46))
        bezierPath.addCurve(to: CGPoint(x: 55.03, y: 114.4), controlPoint1: CGPoint(x: 16.11, y: 91.89), controlPoint2: CGPoint(x: 26.46, y: 100.29))
        bezierPath.addCurve(to: CGPoint(x: 58.94, y: 115.53), controlPoint1: CGPoint(x: 56.3, y: 115.04), controlPoint2: CGPoint(x: 57.76, y: 115.53))
        bezierPath.close()
    
        return bezierPath
    }()