Creating a shadow for a UIImageView that has rounded corners?

▼魔方 西西 提交于 2019-12-17 08:52:47

问题


I am trying to create an ImageView that has rounded corners and a shadow to give it some depth. I was able to create a shadow for the UIImageView, but whenever I added the code to also make it have rounded corners, it only had rounded corners with no shadow. I have an IBOutlet named myImage, and it is inside of the viewDidLoad function. Does anybody have any ideas on how to make it work? What am I doing wrong?

override func viewDidLoad() {
    super.ViewDidLoad() 
    myImage.layer.shadowColor = UIColor.black.cgColor
    myImage.layer.shadowOpacity = 1 
    myImage.layer.shadowOffset = CGSize.zero
    myImage.layer.shadowRadius = 10
    myImage.layer.shadowPath = UIBezierPath(rect: myImage.bounds).cgPath
    myImage.layer.shouldRasterize = false
    myImage.layer.cornerRadius = 10
    myImage.clipsToBounds = true
}

回答1:


If you set clipsToBounds to true, this will round the corners but prevent the shadow from appearing. In order to resolve this, you can create two views. The container view should have the shadow, and its subview should have the rounded corners.

The container view has clipsToBounds set to false, and has the shadow properties applied. If you want the shadow to be rounded as well, use the UIBezierPath constructor that takes in a roundedRect and cornerRadius.

let outerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
outerView.clipsToBounds = false
outerView.layer.shadowColor = UIColor.black.cgColor
outerView.layer.shadowOpacity = 1
outerView.layer.shadowOffset = CGSize.zero
outerView.layer.shadowRadius = 10
outerView.layer.shadowPath = UIBezierPath(roundedRect: outerView.bounds, cornerRadius: 10).cgPath

Next, set the image view (or any other type of UIView) to be the same size of the container view, set clipsToBounds to true, and give it a cornerRadius.

let myImage = UIImageView(frame: outerView.bounds)
myImage.clipsToBounds = true
myImage.layer.cornerRadius = 10

Finally, remember to make the image view a subview of the container view.

outerView.addSubview(myImage)

The result should look something like this:




回答2:


Here is a another solution (tested code) in swift 2.0

If you set clipsToBounds to true, this will round the corners but prevent the shadow from appearing. So, you can add same size UIView in storyboard behind imageview and we can give shadow to that view

SWIFT 2.0

outerView.layer.cornerRadius = 20.0
outerView.layer.shadowColor = UIColor.blackColor().CGColor
outerView.layer.shadowOffset = CGSizeMake(0, 2)
outerView.layer.shadowOpacity = 1
outerView.backgroundColor = UIColor.whiteColor()



回答3:


2019

Finally here is how to

Properly have an image view, with rounded corners AND shadows.

It's this simple:

class ShadowRoundedImageView: UIView {
    @IBInspectable var image: UIImage? = nil {
        didSet {
            imageLayer.contents = image?.cgImage
            shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath }}

    var imageLayer: CALayer = CALayer()
    var shadowLayer: CALayer = CALayer()

    var shape: UIBezierPath {
        return UIBezierPath(roundedRect: bounds, cornerRadius:50) }

    var shapeAsPath: CGPath {
        return shape.cgPath }

    var shapeAsMask: CAShapeLayer {
        let s = CAShapeLayer()
        s.path = shapeAsPath
        return s }

    override func layoutSubviews() {
        super.layoutSubviews()
        clipsToBounds = false
        backgroundColor = .clear

        self.layer.addSublayer(shadowLayer)
        self.layer.addSublayer(imageLayer) // (in that order)

        imageLayer.frame = bounds
        imageLayer.contentsGravity = .resizeAspectFill // (as preferred)

        imageLayer.mask = shapeAsMask
        shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath
        shadowLayer.shadowOpacity = 0.80 // etc ...
    }
}

Here is the

Explanation

  1. UIImageView is useless, you use a UIView

  2. You need two layers, one for the shadow and one for the image

  3. To round an image layer you use a mask

  4. To round a shadow layer you use a path

For the shadow qualities, obviously add code as you see fit

    shadowLayer.shadowOffset = CGSize(width: 0, height: 20)
    shadowLayer.shadowColor = UIColor.purple.cgColor
    shadowLayer.shadowRadius = 5
    shadowLayer.shadowOpacity = 0.80

For the actual shape (the bez path) make it any shape you wish.

(For example this tip https://stackoverflow.com/a/41553784/294884 shows how to make only one or two corners rounded.)

Summary

• Use two layers on a UIView

Make your bezier and ...

• Use a mask on the image layer

• Use a path on the shadow layer




回答4:


You can use a simple class I have created to add image with rounded corners and shadow directly from Storyboard

You can find the class here




回答5:


Swift 5:

You can use the below extension:

extension UIImageView {
func applyshadowWithCorner(containerView : UIView, cornerRadious : CGFloat){
    containerView.clipsToBounds = false
    containerView.layer.shadowColor = UIColor.black.cgColor
    containerView.layer.shadowOpacity = 1
    containerView.layer.shadowOffset = CGSize.zero
    containerView.layer.shadowRadius = 10
    containerView.layer.cornerRadius = cornerRadious
    containerView.layer.shadowPath = UIBezierPath(roundedRect: containerView.bounds, cornerRadius: cornerRadious).cgPath
    self.clipsToBounds = true
    self.layer.cornerRadius = cornerRadious
}

}

How to use:

  1. Drag a UIView on storyboard
  2. Drag a ImageView inside that UIView

Storyboard should look like this:

  1. Create IBOutlet for both View, call extension on your ImageView and pass above created UIView as argument.

Here is the output :



来源:https://stackoverflow.com/questions/41475501/creating-a-shadow-for-a-uiimageview-that-has-rounded-corners

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!