Quelle est la meilleure façon d'append une ombre scope à mon UIView

J'essaie d'append une ombre scope aux vues qui sont superposées les unes sur les autres, les vues se view.clipsToBounds ce qui permet de voir le contenu des autres vues. Dans ce sens, je veux conserver view.clipsToBounds pour que les vues view.clipsToBounds leur contenu est coupé.

Cela semble avoir rendu difficile pour moi d'append une ombre scope aux calques comme quand je tourne des clipsToBounds les ombres sont également coupés.

J'ai essayé de manipuler view.frame et view.bounds afin d'append une ombre scope au cadre mais permettre aux limites d'être assez grandes pour l'englober, mais je n'ai pas eu de chance avec ça.

Voici le code que j'utilise pour append une ombre (cela ne fonctionne qu'avec clipsToBounds OFF comme indiqué)

 view.clipsToBounds = NO; view.layer.shadowColor = [[UIColor blackColor] CGColor]; view.layer.shadowOffset = CGSizeMake(0,5); view.layer.shadowOpacity = 0.5; 

Voici une capture d'écran de l'ombre appliquée à la couche grise la plus claire. J'espère que cela donne une idée de la façon dont mon contenu se chevauchera si clipsToBounds est désactivé.

Application d'ombre.

Comment puis-je append une ombre à mon UIView et conserver mon contenu?

Edit: Je voulais juste append que j'ai aussi joué avec l'utilisation d'images de fond avec des ombres, ce qui fonctionne bien, mais j'aimerais quand même connaître la meilleure solution codée pour cela.

Essaye ça:

 UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:view.bounds]; view.layer.masksToBounds = NO; view.layer.shadowColor = [UIColor blackColor].CGColor; view.layer.shadowOffset = CGSizeMake(0.0f, 5.0f); view.layer.shadowOpacity = 0.5f; view.layer.shadowPath = shadowPath.CGPath; 

Tout d'abord : L' UIBezierPath utilisé comme shadowPath est crucial. Si vous ne l'utilisez pas, vous ne remarquerez peut-être pas une différence au début, mais l'œil vif observera un certain retard lors d'events tels que la rotation de l'appareil et / ou similaire. C'est un tweak de performance important.

En ce qui concerne votre problème en particulier : La ligne importante est view.layer.masksToBounds = NO . Il désactive le découpage des sous-couches de la couche de la vue qui s'étendent plus loin que les limites de la vue.

Pour ceux qui se requestnt quelle est la différence entre masksToBounds (sur le calque) et la propriété clipToBounds la vue: Il n'y en a pas vraiment. Toggle un aura un effet sur l'autre. Juste un niveau différent d'abstraction.


Swift 2.2:

 override func layoutSubviews() { super.layoutSubviews() let shadowPath = UIBezierPath(rect: bounds) layer.masksToBounds = false layer.shadowColor = UIColor.blackColor().CGColor layer.shadowOffset = CGSizeMake(0.0, 5.0) layer.shadowOpacity = 0.5 layer.shadowPath = shadowPath.CGPath } 

Swift 3:

 override func layoutSubviews() { super.layoutSubviews() let shadowPath = UIBezierPath(rect: bounds) layer.masksToBounds = false layer.shadowColor = UIColor.black.cgColor layer.shadowOffset = CGSize(width: 0.0, height: 5.0) layer.shadowOpacity = 0.5 layer.shadowPath = shadowPath.cgPath } 

La réponse de Wasabii dans Swift 2.3:

  let shadowPath = UIBezierPath(rect: view.bounds) view.layer.masksToBounds = false view.layer.shadowColor = UIColor.blackColor().CGColor view.layer.shadowOffset = CGSize(width: 0, height: 0.5) view.layer.shadowOpacity = 0.2 view.layer.shadowPath = shadowPath.CGPath 

Et dans Swift 3/4:

  let shadowPath = UIBezierPath(rect: view.bounds) view.layer.masksToBounds = false view.layer.shadowColor = UIColor.black.cgColor view.layer.shadowOffset = CGSize(width: 0, height: 0.5) view.layer.shadowOpacity = 0.2 view.layer.shadowPath = shadowPath.cgPath 

Placez ce code dans layoutSubviews () si vous utilisez AutoLayout.

L'astuce consiste à définir masksToBounds propriété masksToBounds du masksToBounds de votre vue:

 view.layer.masksToBounds = NO; 

et ça devrait marcher.

( Source )

Sur viewWillLayoutSubviews:

 override func viewWillLayoutSubviews() { sampleView.layer.masksToBounds = false sampleView.layer.shadowColor = UIColor.darkGrayColor().CGColor; sampleView.layer.shadowOffset = CGSizeMake(2.0, 2.0) sampleView.layer.shadowOpacity = 1.0 } 

En utilisant l'extension de UIView:

 extension UIView { func addDropShadowToView(targetView:UIView? ){ targetView!.layer.masksToBounds = false targetView!.layer.shadowColor = UIColor.darkGrayColor().CGColor; targetView!.layer.shadowOffset = CGSizeMake(2.0, 2.0) targetView!.layer.shadowOpacity = 1.0 } } 

Usage:

 sampleView.addDropShadowToView(sampleView) 

Vous pouvez créer une extension pour UIView pour accéder à ces valeurs dans l'éditeur de design

Options d'ombre dans l'éditeur de conception

 extension UIView{ @IBInspectable var shadowOffset: CGSize{ get{ return self.layer.shadowOffset } set{ self.layer.shadowOffset = newValue } } @IBInspectable var shadowColor: UIColor{ get{ return UIColor(cgColor: self.layer.shadowColor!) } set{ self.layer.shadowColor = newValue.cgColor } } @IBInspectable var shadowRadius: CGFloat{ get{ return self.layer.shadowRadius } set{ self.layer.shadowRadius = newValue } } @IBInspectable var shadowOpacity: Float{ get{ return self.layer.shadowOpacity } set{ self.layer.shadowOpacity = newValue } } }