web-dev-qa-db-fra.com

Créer une ombre pour une UIImageView aux coins arrondis?

J'essaie de créer un ImageView qui a des coins arrondis et une ombre pour lui donner de la profondeur. J'ai pu créer une ombre pour le UIImageView, mais chaque fois que j'ajoutais le code pour lui donner des coins arrondis, il n'y avait que des coins arrondis sans ombre. J'ai un IBOutlet nommé myImage, et il est à l'intérieur de la fonction viewDidLoad. Quelqu'un at-il des idées sur la façon de le faire fonctionner? Qu'est-ce que je fais mal?

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
}
17
John Hodge

Si vous définissez clipsToBounds sur true, cela arrondira les coins mais empêchera l'ombre d'apparaître. Pour résoudre ce problème, vous pouvez créer deux vues. La vue conteneur doit avoir l'ombre et sa sous-vue doit avoir les coins arrondis.

La vue du conteneur a clipsToBounds définie sur false et les propriétés d'ombre sont appliquées. Si vous souhaitez que l'ombre soit également arrondie, utilisez le constructeur UIBezierPath qui prend un roundedRect et 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

Ensuite, définissez la vue d'image (ou tout autre type de UIView) pour qu'elle soit de la même taille que la vue du conteneur, définissez clipsToBounds sur true et donnez-lui un cornerRadius.

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

Enfin, n'oubliez pas de faire de la vue d'image une sous-vue de la vue du conteneur.

outerView.addSubview(myImage)

Le résultat devrait ressembler à ceci:

enter image description here

74
nathangitter

Voici une autre solution (code testé) dans Swift 2.

Si vous définissez clipsToBounds sur true, cela arrondira les coins mais empêchera l'ombre d'apparaître. Vous pouvez donc ajouter la même taille UIView dans le storyboard derrière imageview et nous pouvons donner une ombre à cette vue

Swift 2.

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()
5
Hardik Thakkar

Vous pouvez utiliser une classe simple que j'ai créée pour ajouter une image avec des coins arrondis et des ombres directement depuis Storyboard

Vous pouvez trouver la classe ici

Swift_Shadow_ImageView

2
George Leonidas

2019

Enfin, voici comment

Avoir correctement une vue d'image, avec des coins arrondis ET des ombres.

C'est aussi simple que cela:

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 ...
    }
}

Voici la

Explication

  1. UIImageView est inutile, vous utilisez un UIView

  2. Vous avez besoin de deux couches, une pour l'ombre et une pour l'image

  3. Pour arrondir un calque d'image, vous utilisez un masque

  4. Pour arrondir un calque d'ombre, vous utilisez un chemin

Pour les qualités d'ombre, ajoutez évidemment du code comme bon vous semble

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

Pour la forme réelle (le chemin bez), faites-en la forme que vous souhaitez.

(Par exemple, cette astuce https://stackoverflow.com/a/41553784/294884 montre comment ne faire qu'un ou deux coins arrondis.)

Sommaire

• Utilisez deux couches sur un UIView

Faites votre bezier et ...

• Utilisez un masque sur le calque d'image

• Utilisez un chemin sur le calque d'ombre

1
Fattie