Apply a shadow on a UIView that have same corner radius than view

后端 未结 2 1927
星月不相逢
星月不相逢 2020-12-20 09:28

Hello i have some views with rounded corners, and I\'d like to apply a shadow to this views.

SO first I round the view :

view.layer.cornerRadius = 15         


        
相关标签:
2条回答
  • 2020-12-20 10:27

    You cannot cast a shadow from a view whose clipsToBounds is true. If a view's masksToBounds is true, its clipsToBounds is true; they are the same thing.

    If you want a shadow to appear to come from from a view that clips, you need to use two views: one that the user can see, with rounded corners and clipsToBounds set to true, and another that the user can't see because it's behind the first one, also with rounded corners, but with clipsToBounds set to false, to cast the shadow.

    class ShadowView : UIView {
        override init(frame: CGRect) {
            super.init(frame:frame)
            self.isOpaque = true
            self.backgroundColor = .black
            self.dropShadow()
        }
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        func dropShadow() {
            self.layer.masksToBounds = false
            self.layer.cornerRadius = 15
            self.layer.shadowColor = UIColor.black.cgColor
            self.layer.shadowOffset = CGSize(width: 3, height: 3)
            self.layer.shadowOpacity = 0.5
            self.layer.shadowRadius = 5
        }
    }
    
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            let r = CGRect(x: 100, y: 100, width: 100, height: 100)
            let v = UIImageView(frame:r)
            v.image = UIImage(named:"marsSurface.jpg")
            v.clipsToBounds = true
            v.backgroundColor = .red
            v.layer.cornerRadius = 15
            self.view.addSubview(ShadowView(frame:r))
            self.view.addSubview(v)
        }
    }
    

    Note that neither view is a subview of the other, nor do they have a superview that clips, as that would clip the shadow.

    0 讨论(0)
  • 2020-12-20 10:29

    Trying to have a single view handle both corner rounding and shadow logic is not recommended. The best way to create the effect you are looking for is to wrap your rounded view with another parent view that owns the shadow.

    This can be best illustrated with a playground. Try this code out in a playground.

    import UIKit
    import PlaygroundSupport
    
    class MyViewController : UIViewController {
      override func loadView() {
        let view = UIView()
        view.backgroundColor = .white
    
        let shadowView = UIView()
        shadowView.frame = CGRect(x: 50, y: 200, width: 200, height: 100)
        shadowView.backgroundColor = nil
        shadowView.layer.shadowColor = UIColor.black.cgColor
        shadowView.layer.shadowOffset = CGSize(width: 0, height: 4.0)
        shadowView.layer.shadowRadius = 8.0
        shadowView.layer.shadowOpacity = 1
    
        let roundedView = UIView()
        roundedView.frame = shadowView.bounds
        roundedView.backgroundColor = .gray
        roundedView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner,.layerMaxXMinYCorner]
        roundedView.layer.cornerRadius = 10
        roundedView.layer.masksToBounds = true
    
        shadowView.addSubview(roundedView)
        view.addSubview(shadowView)
    
        view.backgroundColor = UIColor.white
        self.view = view
      }
    }
    // Present the view controller in the Live View window
    PlaygroundPage.current.liveView = MyViewController()
    

    Don't forget to set the shadowPath property on your shadow view's layer in either viewWillLayoutSubviews or layoutSubviews. If this property is set to nil, UIKit has to perform off screen rendering to figure out how to draw the shadow rect.

    0 讨论(0)
提交回复
热议问题