Can't set cornerRadius AND shadow on layer that has an image view stretched to its bounds?

前端 未结 5 681
醉话见心
醉话见心 2020-12-31 03:00

This is stumping me. I have a UIView (call it \"parent\"). The bottommost subview of that view is a UIImageView (call it \"child\"), whose frame occupies the entirety of the

相关标签:
5条回答
  • 2020-12-31 03:29

    With Swift 3, you can choose one of the two following code snippets in order to set cornerRadius and shadow on an image view or on a view that contains an image layer.


    #1. Using UIView, CALayer and Spring and Struts

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // constants
            let radius: CGFloat = 20, dimension: CGFloat = 200, offset = 8
            let frame = CGRect(x: 0, y: 0, width: 200, height: 200)
    
            // custom view
            let customView = UIView(frame: frame)
            customView.contentMode = .scaleAspectFill
    
            // image layer
            let imageLayer = CALayer()
            imageLayer.contentsGravity = kCAGravityResizeAspectFill
            imageLayer.contents = UIImage(named: "image")!.cgImage
            imageLayer.masksToBounds = true
            imageLayer.frame = frame
            imageLayer.cornerRadius = radius
            imageLayer.masksToBounds = true
    
            // rounded layer
            let roundedLayer = CALayer()
            roundedLayer.shadowColor = UIColor.darkGray.cgColor
            roundedLayer.shadowPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: dimension, height: dimension), cornerRadius: radius).cgPath
            roundedLayer.shadowOffset = CGSize(width: offset, height: offset)
            roundedLayer.shadowOpacity = 0.8
            roundedLayer.shadowRadius = 2
            roundedLayer.frame = frame
    
            // views and layers hierarchy
            customView.layer.addSublayer(imageLayer)
            customView.layer.insertSublayer(roundedLayer, below: imageLayer)
            view.addSubview(customView)
    
            // layout
            customView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
            customView.autoresizingMask = [UIViewAutoresizing.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
        }
    
    }
    

    #2. Using UIView, UIImageView, CALayer and Auto Layout

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // constants
            let radius: CGFloat = 20, dimension: CGFloat = 200, offset = 8
    
            // image view
            let imageView = UIImageView(image: UIImage(named: "image"))
            imageView.contentMode = .scaleAspectFill
            imageView.layer.cornerRadius = radius
            imageView.layer.masksToBounds = true
    
            // rounded view
            let roundedView = UIView()
            roundedView.layer.shadowColor = UIColor.darkGray.cgColor
            roundedView.layer.shadowPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: dimension, height: dimension), cornerRadius: radius).cgPath
            roundedView.layer.shadowOffset = CGSize(width: offset, height: offset)
            roundedView.layer.shadowOpacity = 0.8
            roundedView.layer.shadowRadius = 2
    
            // views hierarchy
            roundedView.addSubview(imageView)
            view.addSubview(roundedView)
    
            // layout
            imageView.translatesAutoresizingMaskIntoConstraints = false
            roundedView.translatesAutoresizingMaskIntoConstraints = false
            roundedView.widthAnchor.constraint(equalToConstant: dimension).isActive = true
            roundedView.heightAnchor.constraint(equalToConstant: dimension).isActive = true
            imageView.widthAnchor.constraint(equalTo: roundedView.widthAnchor).isActive = true
            imageView.heightAnchor.constraint(equalTo: roundedView.heightAnchor).isActive = true
            roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
            imageView.centerXAnchor.constraint(equalTo: roundedView.centerXAnchor).isActive = true
            imageView.centerYAnchor.constraint(equalTo: roundedView.centerYAnchor).isActive = true
        }
    
    }
    

    Both code snippets generate the following display:


    You can find more ways to combine images with rounded corners and shadow on this Github repo.

    0 讨论(0)
  • 2020-12-31 03:33

    Normally you have to set clipsToBounds to have rounded corners, but since you want to retain the shadow you have to round the corners of the shadow as well. Have you tried setting the shadow path using a bezier path? Keep clipsToBounds/masksToBounds to the default, NO. Something like:

      [[parent layer] setCornerRadius:6.0f];
      [[parent layer] setShadowPath:
                 [[UIBezierPath bezierPathWithRoundedRect:[parent bounds] 
                       cornerRadius:6.0f] CGPath]];
    
    0 讨论(0)
  • 2020-12-31 03:37

    If you want shadow layer with corner radius for imageview is that better solution put imageview a view as subview with 1 point margin.. and

     imgBrandLogo.backgroundColor = UIColor.blue
        imgBrandLogo.layer.cornerRadius = imgBrandLogo.frame.height/2
        imgBrandLogo.clipsToBounds = true
        viewBrandLogo.layer.shadowColor = UIColor(rgb:0x262626,alpha:0.24).cgColor
        viewBrandLogo.layer.shadowOffset = CGSize(width: 0, height: 1)
        viewBrandLogo.layer.shadowOpacity = 1
        viewBrandLogo.layer.shadowPath = UIBezierPath(roundedRect:imgBrandLogo.bounds , cornerRadius: imgBrandLogo.frame.height/2).cgPath
        viewBrandLogo.backgroundColor = UIColor.clear.withAlphaComponent(0.0)
    
    0 讨论(0)
  • 2020-12-31 03:44

    Have you tried setting the bounds of the child UIImageView so that it also has rounded corners? Perhaps then it wouldn't override the shadow of the container view. Just a thought, not sure if it will work.

    0 讨论(0)
  • 2020-12-31 03:46

    You will need two nested views, the inner one setting rounded corners and clipping to bound, and the outer view having the shadow (and therefore not clipping). In your case inner and outer view will probably be "child" and "parent", but I guess you didn't set the right clipping values for these views?

    See the answer in Why masksToBounds = YES prevents CALayer shadow?.

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