UIView avec coins arrondis et ombre portée?

390

Je veux une personnalisation UIView...: je voulais juste une vue blanche vierge avec des coins arrondis et une ombre légère (sans effet d'éclairage). Je peux faire chacun de ceux-ci un par un mais les habituels clipToBounds/ maskToBoundsconflits se produisent.

Aditya Vaidyam
la source
1
Puisque vous dites dans un commentaire ci-dessous que vous avez obtenu que cela fonctionne avec CoreGraphics, cela vous dérangerait-il de partager la réponse avec la communauté afin que vous puissiez aider les autres dans la même situation, comme ils ont essayé de vous aider?
lnafziger
Je suis désolé, c'était il y a longtemps, et je n'ai plus la source. Ce que j'ai fait était de remplacer -drawRect: et d'utiliser UIBezierPath pour dessiner un rectangle, et appliquer une ombre au calque soutenant la vue ... si je me souviens bien. :)
Aditya Vaidyam
5
La réponse acceptée ne fonctionne pas!
onmyway133
1
@Sachavijay Vous devez vérifier les dates des deux messages avant de commenter.
Aditya Vaidyam

Réponses:

443

L'extrait de code suivant ajoute une bordure, un rayon de bordure et une ombre portée à v, a UIView:

// border radius
[v.layer setCornerRadius:30.0f];

// border
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[v.layer setBorderWidth:1.5f];

// drop shadow
[v.layer setShadowColor:[UIColor blackColor].CGColor];
[v.layer setShadowOpacity:0.8];
[v.layer setShadowRadius:3.0];
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)];

Vous pouvez ajuster les paramètres en fonction de vos besoins.

Ajoutez également le framework QuartzCore à votre projet et:

#import <QuartzCore/QuartzCore.h>

Voir mon autre réponse concernant masksToBounds.


Remarque

Cela peut ne pas fonctionner dans tous les cas. Si vous constatez que cette méthode interfère avec d'autres opérations de dessin que vous effectuez, consultez cette réponse .

Evan Mulawski
la source
83
Eh bien, le problème est que lorsque je définis le rayon des coins, il définit maskToBounds: YES, tandis que l'ombre nécessite clipToBounds: NO (où clipToBounds fait la même chose que maskToBounds)
Aditya Vaidyam
15
Même problème ici. Si j'ai une couleur d'arrière-plan, je veux qu'elle soit coupée dans les coins arrondis. Pour ce faire, je dois utiliser maskToBounds = TRUE, mais l'ombre disparaît ensuite.
hfossli
3
Pour les débutants comme moi: j'ai dû importer le framework QuartzCore dans mon projet afin d'appeler des méthodes sur l'objet calque.
SilithCrowe
38
Pour que cela fonctionne correctement, utilisez une vue de conteneur interne, qui abritera votre bordure et votre couleur d'arrière-plan, toutes deux avec un rayon d'angle. Cette vue sera tronquée! La deuxième vue du conteneur externe abritera la première, a le même cadre, avec juste une ombre portée. J'ai fait cela plusieurs fois pour combiner une bordure, une ombre portée et un rayon de coin. C'est vraiment ennuyeux, mais ça marche vraiment bien.
Kpmurphy91
23
Ça ne marche pas. Je ne sais pas pourquoi il y a tant de votes positifs. Était-ce applicable dans les anciennes versions?
Yarneo
629

Rapide

entrez la description de l'image ici

// corner radius
blueView.layer.cornerRadius = 10

// border
blueView.layer.borderWidth = 1.0
blueView.layer.borderColor = UIColor.black.cgColor

// shadow
blueView.layer.shadowColor = UIColor.black.cgColor
blueView.layer.shadowOffset = CGSize(width: 3, height: 3)
blueView.layer.shadowOpacity = 0.7
blueView.layer.shadowRadius = 4.0

Explorer les options

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

Problème 1: l'ombre est coupée

Et s'il y a des sous-couches ou des sous-vues (comme une image) dont nous voulons couper le contenu aux limites de notre vue?

entrez la description de l'image ici

Nous pouvons accomplir cela avec

blueView.layer.masksToBounds = true

(Alternativement, blueView.clipsToBounds = truedonne le même résultat .)

entrez la description de l'image ici

Mais, oh non! L'ombre a également été coupée car elle est en dehors des limites! Que faire? Que faire?

Solution

Utilisez des vues distinctes pour l'ombre et la bordure. La vue de base est transparente et présente l'ombre. La vue de bordure découpe tout autre sous-contenu dont elle dispose sur ses bordures.

// add the shadow to the base view
baseView.backgroundColor = UIColor.clear
baseView.layer.shadowColor = UIColor.black.cgColor
baseView.layer.shadowOffset = CGSize(width: 3, height: 3)
baseView.layer.shadowOpacity = 0.7
baseView.layer.shadowRadius = 4.0

// add the border to subview
let borderView = UIView()
borderView.frame = baseView.bounds
borderView.layer.cornerRadius = 10
borderView.layer.borderColor = UIColor.black.cgColor
borderView.layer.borderWidth = 1.0
borderView.layer.masksToBounds = true
baseView.addSubview(borderView)

// add any other subcontent that you want clipped
let otherSubContent = UIImageView()
otherSubContent.image = UIImage(named: "lion")
otherSubContent.frame = borderView.bounds
borderView.addSubview(otherSubContent)

Cela donne le résultat suivant:

entrez la description de l'image ici

Problème 2: performances médiocres

Ajouter des coins arrondis et des ombres peut être un succès. Vous pouvez améliorer les performances en utilisant un chemin prédéfini pour l'ombre et en spécifiant également qu'il doit être pixellisé. Le code suivant peut être ajouté à l'exemple ci-dessus.

baseView.layer.shadowPath = UIBezierPath(roundedRect: baseView.bounds, cornerRadius: 10).cgPath
baseView.layer.shouldRasterize = true
baseView.layer.rasterizationScale = UIScreen.main.scale

Voir cet article pour plus de détails. Voir ici et ici aussi.

Cette réponse a été testée avec Swift 4 et Xcode 9.

Suragch
la source
1
@ EICaptainv2.0, Si vous ne voulez qu'une bordure (et / ou un rayon d'angle), vous n'avez pas besoin d'une vue séparée. La vue séparée est pour la situation où vous avez besoin de coins arrondis et d' ombres .
Suragch
2
Ça ne marche pas pour moi. Lorsque je mets la couleur de fond à effacer sur la baseView, aucune ombre n'apparaît plus. Qu'est-ce que je fais mal?
Rutger Huijsmans
3
Ne fonctionne pas, le réglage baseView.backgroundColor = UIColor.clearsupprime l'ombre. Ce n'est que si vous définissez une couleur d'arrière-plan que vous la verrez.
Aleksander
2
NE FONCTIONNE PAS POUR MOI.
Markus
4
Pour info, je voyais initialement le même problème que d'autres commentateurs voyaient où l'ombre de la baseView ne s'affichait pas lorsque sa couleur d'arrière-plan était claire. Le problème était que je n'exécutais que la première partie du code (le truc baseView). Une fois que j'ai ajouté borderView en tant que sous-vue, l'ombre a commencé à s'afficher. Il semble que pour que l'ombre s'affiche, il doit y avoir au moins une bordure (ou arrière-plan) visible dans sa hiérarchie de vues. Assurez-vous donc d'avoir borderView.layer.borderWidth> = 0 avec un borderView.layer.borderColor non transparent (ou une couleur d'arrière-plan non transparente)
Mike Vosseller
79

Une façon de procéder consiste à placer la vue avec des coins arrondis dans une vue avec l'ombre portée.

UIView* roundedView = [[UIView alloc] initWithFrame: frame];
roundedView.layer.cornerRadius = 5.0;
roundedView.layer.masksToBounds = YES;

UIView* shadowView = [[UIView alloc] initWithFrame: frame];
shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
shadowView.layer.shadowRadius = 5.0;
shadowView.layer.shadowOffset = CGSizeMake(3.0, 3.0);
shadowView.layer.shadowOpacity = 1.0;
[shadowView addSubview: roundedView];

Ensuite, vous pouvez ajouter le shadowView où vous le souhaitez.

David C.
la source
5
Amit, vous devez définir maskToBounds / clipToBounds = YES pour le * roundView uniquement *. NE définissez PAS cela sur shadowView. Je n'ai pas essayé le code ci-dessus mais je suis sûr que cette solution fonctionne certainement mais pas idéale. Le shadowRadius supérieur prend soin des zones de rayon d'angle. Réglez shadowRadius sur 0 ou 1 et vous remarquerez ce que j'essaie de dire.
Deepak GM
2
Quelque chose comme shadowView.layer.shadowOpacity = 0.6; est manquant
Bo.
3
"shadowView.layer.opacity = 1.0" devrait être "shadowView.layer.shadowOpacity = 1.0"
Chris
Fonctionne sur iOS 9 si utilisez shadowView.layer.shadowOpacity = 1.0
Mansurov Ruslan
Code corrigé pour shadowOpacity
Softlion
63

Consultez l' exemple de projet sur GitHub pour vous assurer que vous utilisez correctement le composant.

Solution Swift 5 simple sans sous-vues ni sous-classes supplémentaires:

extension UIView {

    func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
        layer.masksToBounds = false
        layer.shadowOffset = offset
        layer.shadowColor = color.cgColor
        layer.shadowRadius = radius
        layer.shadowOpacity = opacity

        let backgroundCGColor = backgroundColor?.cgColor
        backgroundColor = nil
        layer.backgroundColor =  backgroundCGColor
    }
}

Notez que vous devez configurer votre vue avec un rayon d'angle et d'autres propriétés avant d'appeler addShadow .

Après cela, il suffit d'appeler viewDidLoadcomme ceci:

button.addShadow(offset: CGSize.init(width: 0, height: 3), color: UIColor.black, radius: 2.0, opacity: 0.35)

Résultat final:

résultat

Super facile et simple!

Sergey Grischyov
la source
Est-ce que cela fonctionne sur les boutons? Parce que ça ne marche pas de mon côté.
Cesare
J'ai essayé de suivre les étapes exactes que vous avez suggérées. Mais toujours pas de chance. Ce serait formidable si vous partagez un échantillon (sur Github) pour voir comment vous avez fait ce qui semble impossible pour moi et pour les autres.
Hemang
A réussi à le faire fonctionner uniquement en supprimant cette ligne layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath. Je ne peux pas expliquer pourquoi cependant, quelqu'un a-t-il une explication à cela?
trupin
@Curnelious n'hésitez pas à jeter un œil à la réponse mise à jour avec un exemple de projet Xcode. Cela ne peut pas ne pas fonctionner :)
Sergey Grischyov
3
Cela a fonctionné pour moi aussi, juste une chose de plus à faire pour effacer toutes les couleurs d'arrière-plan des sous-vues afin que seule la vue du conteneur ait un arrière-plan visible et cela a résolu mon problème. Merci!! @SergeyGrischyov
Rishabh
42

Cela a fonctionné pour moi. L'astuce consistait à déplacer la couleur d'arrière-plan de la vue principale vers le calque.

CALayer *layer = view.layer;
layer.cornerRadius = 15.0f;
layer.masksToBounds = NO;

layer.shadowOffset = CGSizeMake(0, 3);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowRadius = 2.0f;
layer.shadowOpacity = 0.35f;
layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:layer.cornerRadius] CGPath];

CGColorRef  bColor = view.backgroundColor.CGColor;
view.backgroundColor = nil;
layer.backgroundColor =  bColor ;
Ade
la source
Bien que toutes les autres solutions fonctionnent, et peut-être qu'elles soient plus générales, c'est de loin la meilleure solution au problème. L'ajout de sous-vues ou de sous-couches crée un monde ou des difficultés à maintenir les tailles de trame ou, au mieux, peut entraîner des problèmes de performances.
emem
Cela devrait être la réponse. Propre et élégant.
Axy
Meilleure solution et définitivement élégante!
Roberto Ferraz
Wow, cela fonctionne réellement. Je ne comprends pas pourquoi cela devrait fonctionner - vous penseriez que backgroundColor de la vue correctement serait directement mappé à la propriété layer.backgroundColor sur iOS - mais cela FONCTIONNE. (Xcode 8, Swift 3.) Bravo et merci. Ce devrait être la réponse acceptée.
Womble
J'ai créé une version Swift 3.1 de votre réponse en utilisant UIView extensionici - stackoverflow.com/a/43295741/1313939 merci pour l'inspiration!
Sergey Grischyov le
26

J'ai résolu le problème en utilisant l'astuce suivante lors de l'attribution du chemin d'ombre pour la vue du conteneur:

[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]

Notez que le chemin donné à l'ombre est un rectangle arrondi avec le même rayon de coin que l'arrière-plan que contient la cellule:

//this is the border for the UIView that is added to a cell
cell.backgroundView.layer.cornerRadius = 12;
cell.backgroundView.layer.masksToBounds = YES;
cell.backgroundView.layer.borderColor = [UIColor darkGrayColor].CGColor;
cell.backgroundView.layer.borderWidth = 1;

//this is the shadow around the cell itself (cannot have round corners with borders and shadow, need to use two views
cell.layer.shadowRadius = 2;
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = NO;
[[cell layer] setShadowColor:[[UIColor darkGrayColor] CGColor]];

[[cell layer] setShadowOffset:CGSizeMake(0.0,0.0)];
[[cell layer] setShadowOpacity:1.0];

UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12];
[[cell layer] setShadowPath:[path CGPath]];
Alex Stone
la source
Meilleure réponse car elle explique la bonne façon d'ajouter de l'ombre à une vue plus arrondie. Merci @Alex Stone
programmeur
17

Si vous rencontrez des difficultés à cause de l'arrondi cornersvs subviewsvs masksToBounds, essayez d'utiliser ma fonction:

- (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
    CGRect shadowFrame; // Modify this if needed
    shadowFrame.size.width = 0.f;
    shadowFrame.size.height = 0.f;
    shadowFrame.origin.x = 0.f;
    shadowFrame.origin.y = 0.f;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
    shadow.userInteractionEnabled = NO; // Modify this if needed
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    [view.superview insertSubview:shadow belowSubview:view];
    [shadow addSubview:view];
    return shadow;
}

appelez-le sur votre vue. si votre vue a des coins arrondis, peu importe sa taille, sa forme - une belle ombre sera dessinée.

Conservez simplement la valeur de retour de la fonction afin de pouvoir vous y référer lorsque vous souhaitez supprimer la table (ou par exemple l'utiliser insertSubview:aboveView:)

daniel.gindi
la source
ça fonctionne bien. Mais si la vue dispose de reconnaisseurs de gestes, cela ne fonctionnera pas. comment le résoudre?
manujmv
@manujmv Voyez-vous les lignes où "// Modifiez ceci si nécessaire" est spécifié? Voilà ce dont vous avez besoin. shadow.userInteractionEnabled = YES;
daniel.gindi
@manujmv, alors vous devriez tester les cadres de la vue et de la sous-vue pour voir pourquoi. quelque chose n'est probablement pas là. ce code exact fonctionne pour moi dans de très belles applications
daniel.gindi
2
Cette solution fonctionne très bien pour UITableViews avec des coins arrondis. J'aimerais pouvoir lui donner plus de votes. Merci!
Chris Hart
@ CarlosEduardoLópez Voyez-vous la shadow.userInteractionEnabled = NO; // Modify this if neededligne? C'est donc le cas là où c'est nécessaire. userInteractionEnabledest une propriété basique et populaire que vous devriez déjà connaître :-)
daniel.gindi
12

En utilisant Swift 4 et Xcode 9 , ceci est un exemple de travail d'arrondi ImageViewavec une ombre portée et une bordure.

    //set dimensions and position of image (in this case, centered)
    let imageHeight: CGFloat = 150, imageWidth: CGFloat = 150
    let xPosition = (self.view.frame.width / 2) - (imageWidth / 2)
    let yPosition = (self.view.frame.height / 2) - (imageHeight / 2)

    //set desired corner radius
    let cornerRadius: CGFloat = 20

    //create container for the image
    let imageContainer = UIView(frame: CGRect(x: xPosition, y: yPosition, width: imageWidth, height: imageHeight))

    //configure the container
    imageContainer.clipsToBounds = false
    imageContainer.layer.shadowColor = UIColor.black.cgColor
    imageContainer.layer.shadowOpacity = 1
    imageContainer.layer.shadowOffset = CGSize(width: 3.0, height: 3.0)
    imageContainer.layer.shadowRadius = 5
    imageContainer.layer.shadowPath = UIBezierPath(roundedRect: imageContainer.bounds, cornerRadius: cornerRadius).cgPath

    //create imageView
    let imageView = UIImageView(frame: imageContainer.bounds)

    //configure the imageView
    imageView.clipsToBounds = true
    imageView.layer.cornerRadius = cornerRadius
    //add a border (if required)
    imageView.layer.borderColor = UIColor.black.cgColor
    imageView.layer.borderWidth = 1.0
    //set the image
    imageView.image = UIImage(named: "bird")

    //add the views to the superview
    view.addSubview(imageContainer)
    imageContainer.addSubview(imageView)

entrez la description de l'image ici

Si vous voulez que l'image soit circulaire: (et montrée sans bordure)

let cornerRadius = imageWidth / 2

entrez la description de l'image ici

rbaldwin
la source
7

J'ai créé un assistant sur UIView

@interface UIView (Helper)

- (void)roundCornerswithRadius:(float)cornerRadius
               andShadowOffset:(float)shadowOffset;
@end

vous pouvez l'appeler comme ça

[self.view roundCornerswithRadius:5 andShadowOffset:5];

Voici l'implémentation

- (void)roundCornerswithRadius:(float)cornerRadius
               andShadowOffset:(float)shadowOffset
{
    const float CORNER_RADIUS = cornerRadius;
    const float SHADOW_OFFSET = shadowOffset;
    const float SHADOW_OPACITY = 0.5;
    const float SHADOW_RADIUS = 3.0;

    UIView *superView = self.superview;

    CGRect oldBackgroundFrame = self.frame;
    [self removeFromSuperview];

    CGRect frameForShadowView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
    UIView *shadowView = [[UIView alloc] initWithFrame:frameForShadowView];
    [shadowView.layer setShadowOpacity:SHADOW_OPACITY];
    [shadowView.layer setShadowRadius:SHADOW_RADIUS];
    [shadowView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];

    [self.layer setCornerRadius:CORNER_RADIUS];
    [self.layer setMasksToBounds:YES];

    [shadowView addSubview:self];
    [superView addSubview:shadowView];

}
Zayin Krige
la source
2
C'est une bonne solution élégante. Assurez-vous que votre vue a été ajoutée à sa vue d'ensemble avant utilisation. J'ai ajouté quelques paramètres pour me donner plus de contrôle sur l'ombre, mais dans l'ensemble, cela fonctionne parfaitement. Merci!
Aaron Vegh
C'est une bonne solution mais cela ne fonctionne pas avec la mise en page automatique: la vue sera dessinée sur l'origine 0,0
gderaco
5

Après une journée entière de recherche sur la vue du coin arrondi avec l'ombre, je suis heureux de poster mon cours uiview personnalisé ici, j'espère terminer cette question:

RoundCornerShadowView.h

#import <UIKit/UIKit.h>

@interface RoundCornerShadowView : UIView

@end

RoundCornerShadowView.m

#import "RoundCornerShadowView.h"

@implementation RoundCornerShadowView

// *** must override this method, not the other method ***
// otherwise, the background corner doesn't disappear....
// @2015/05/29
-(void) layoutSubviews {
    [super layoutSubviews];//is must to ensure rightly layout children view

    //1. first, create Inner layer with content
    CALayer *innerView = [CALayer layer];
    innerView.frame = CGRectMake(0,0,self.bounds.size.width,self.bounds.size.height);
    //instead of: innerView.frame = self.frame;
    innerView.borderWidth = 1.0f;
    innerView.cornerRadius = 6.0f;
    innerView.masksToBounds = YES;
    innerView.borderColor = [[UIColor lightGrayColor] CGColor];
    innerView.backgroundColor = [[UIColor whiteColor] CGColor];
    //put the layer to the BOTTOM of layers is also a MUST step...
    //otherwise this layer will overlay the sub uiviews in current uiview...
    [self.layer insertSublayer:innerView atIndex:0];

    //2. then, create shadow with self layer
    self.layer.masksToBounds = NO;
    self.layer.shadowColor = [[UIColor darkGrayColor] CGColor];
    self.layer.shadowOpacity = 0.4f;
    //shadow length
    self.layer.shadowRadius = 2.0f;
    //no offset
    self.layer.shadowOffset = CGSizeMake(0, 0);
    //right down shadow
    //[self.layer setShadowOffset: CGSizeMake(1.0f, 1.0f)];

    //3. last but important, MUST clear current view background color, or the color will show in the corner!
    self.backgroundColor = [UIColor clearColor];
}

@end

donc, PAS besoin d'ajouter de sous-vue dans la vue ou ci-dessous dans la vue cible, ajoutez simplement une couche dans la vue actuelle et faites 3 étapes pour la terminer!

regardez attentivement les commentaires dans le code, il est utile de comprendre le composant!

lwz7512
la source
5

Quelque chose de swifty testé dans swift 4

import UIKit

extension UIView {
    @IBInspectable var dropShadow: Bool {
        set{
            if newValue {
                layer.shadowColor = UIColor.black.cgColor
                layer.shadowOpacity = 0.4
                layer.shadowRadius = 1
                layer.shadowOffset = CGSize.zero
            } else {
                layer.shadowColor = UIColor.clear.cgColor
                layer.shadowOpacity = 0
                layer.shadowRadius = 0
                layer.shadowOffset = CGSize.zero
            }
        }
        get {
            return layer.shadowOpacity > 0
        }
    }
}

Produit

entrez la description de l'image ici

Si vous l'activez dans l'inspecteur comme ceci:

entrez la description de l'image ici

Il ajoutera l'attribut d'exécution défini par l'utilisateur, résultant en:

entrez la description de l'image ici

(J'ai ajouté précédemment le cornerRadius = 8)

:)

dGambit
la source
5

Vous devez utiliser use shadowViewetroundView

entrez la description de l'image ici

shadowView

  • Doit avoir une couleur d'arrière-plan
  • Devrait rester derrière roundView
  • L'astuce consiste à disposer shadowViewun peu à l'intérieur, et son ombre doit briller. Ajustez le insetspour qu'il shadowViewsoit complètement invisible derrièreroundView

roundView

  • Doit clipser les sous-vues

Le code

addSubviews(shadowView, roundView)
roundView.addSubviews(titleLabel, subtitleLabel, imageView)

// need inset
shadowView.pinEdges(view: self, inset: UIEdgeInsets(constraintInsets: 2))
roundView.pinEdges(view: self)

do {
  shadowView.backgroundColor = .white // need background
  let layer = shadowView.layer
  layer.shadowColor = UIColor.black.cgColor
  layer.shadowRadius = 3
  layer.shadowOffset = CGSize(width: 3, height: 3)
  layer.shadowOpacity = 0.7
  layer.shouldRasterize = true
}

do {
  roundView.backgroundColor = .white
  let layer = roundView.layer
  layer.masksToBounds = true
  layer.cornerRadius = 5
}

Ou vous pouvez simplement faire ci-dessous sans préciser clipToBounds/maskToBounds

layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.8
onmyway133
la source
4

Swift 3 & IBInspectable solution:
Inspiré par la solution d'Ade

Créez d'abord une extension UIView:

//
//  UIView-Extension.swift
//  

import Foundation
import UIKit

@IBDesignable
extension UIView {
     // Shadow
     @IBInspectable var shadow: Bool {
          get {
               return layer.shadowOpacity > 0.0
          }
          set {
               if newValue == true {
                    self.addShadow()
               }
          }
     }

     fileprivate func addShadow(shadowColor: CGColor = UIColor.black.cgColor, shadowOffset: CGSize = CGSize(width: 3.0, height: 3.0), shadowOpacity: Float = 0.35, shadowRadius: CGFloat = 5.0) {
          let layer = self.layer
          layer.masksToBounds = false

          layer.shadowColor = shadowColor
          layer.shadowOffset = shadowOffset
          layer.shadowRadius = shadowRadius
          layer.shadowOpacity = shadowOpacity
          layer.shadowPath = UIBezierPath(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath

          let backgroundColor = self.backgroundColor?.cgColor
          self.backgroundColor = nil
          layer.backgroundColor =  backgroundColor
     }


     // Corner radius
     @IBInspectable var circle: Bool {
          get {
               return layer.cornerRadius == self.bounds.width*0.5
          }
          set {
               if newValue == true {
                    self.cornerRadius = self.bounds.width*0.5
               }
          }
     }

     @IBInspectable var cornerRadius: CGFloat {
          get {
               return self.layer.cornerRadius
          }

          set {
               self.layer.cornerRadius = newValue
          }
     }


     // Borders
     // Border width
     @IBInspectable
     public var borderWidth: CGFloat {
          set {
               layer.borderWidth = newValue
          }

          get {
               return layer.borderWidth
          }
     }

     // Border color
     @IBInspectable
     public var borderColor: UIColor? {
          set {
               layer.borderColor = newValue?.cgColor
          }

          get {
               if let borderColor = layer.borderColor {
                    return UIColor(cgColor: borderColor)
               }
               return nil
          }
     }
}

Ensuite, sélectionnez simplement votre UIView dans le générateur d'interface en définissant l' ombre et le rayon d'angle , comme ci-dessous:

Sélection de votre UIView

Définition de l'ombre et du rayon d'angle

Le résultat!

Résultat

Thomás Calmon
la source
Comme toutes les autres «solutions» de ce fil, cela ne fonctionne tout simplement pas, du moins pas sur iOS 11.0 / Swift 4.1.
inexcit
Avez-vous lu "Swift 3" au début du fil? Donc, cela signifie que c'est une solution Swift 3, je ne l'ai pas testée dans Swift 4.1 parce que je n'en ai plus besoin. N'hésitez pas à modifier la réponse et à donner une solution. ;) Cheers
Thomás Calmon
3

Voici la solution au problème de conflit masksToBounds, cela fonctionne pour moi.

Après avoir défini corderRadius / borderColor / shadow et ainsi de suite, définissez masksToBounds sur NO:

v.layer.masksToBounds = NO;
Shaopeng Wang
la source
Cela a fonctionné pour moi !! omg j'ai presque fait toutes les astuces au-dessus de vous répondre! merci Shaopeng.
MontDeska
3

Ombre + bordure + rayon d'angle entrez la description de l'image ici

    scrollview.backgroundColor = [UIColor whiteColor]; 
    CALayer *ScrlViewLayer = [scrollview layer];
    [ScrlViewLayer setMasksToBounds:NO ];
    [ScrlViewLayer setShadowColor:[[UIColor lightGrayColor] CGColor]];
    [ScrlViewLayer setShadowOpacity:1.0 ];
    [ScrlViewLayer setShadowRadius:6.0 ];
    [ScrlViewLayer setShadowOffset:CGSizeMake( 0 , 0 )];
    [ScrlViewLayer setShouldRasterize:YES];
    [ScrlViewLayer setCornerRadius:5.0];
    [ScrlViewLayer setBorderColor:[UIColor lightGrayColor].CGColor];
    [ScrlViewLayer setBorderWidth:1.0];
    [ScrlViewLayer setShadowPath:[UIBezierPath bezierPathWithRect:scrollview.bounds].CGPath];
Darshit Shah
la source
3

Voici ma version dans Swift 3 pour une UIView

let corners:UIRectCorner = [.bottomLeft, .topRight]
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()

mask.path = path.cgPath
mask.fillColor = UIColor.white.cgColor

let shadowLayer = CAShapeLayer()
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowOffset = CGSize(width: 0.0, height: 4.0)
shadowLayer.shadowRadius = 6.0
shadowLayer.shadowOpacity = 0.25
shadowLayer.shadowPath = mask.path

self.layer.insertSublayer(shadowLayer, at: 0)
self.layer.insertSublayer(mask, at: 1)
Yung Dai
la source
3

Swift 4: créer une sous-classe d'UIView

class ShadowView: UIView {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // corner radius
        self.layer.cornerRadius = 10

        // border
        self.layer.borderWidth = 1.0
        self.layer.borderColor = UIColor.black.cgColor

        // shadow
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOffset = CGSize(width: 3, height: 3)
        self.layer.shadowOpacity = 0.7
        self.layer.shadowRadius = 4.0
    }

}

En utilisant..

Utiliser la vue d'ombre de classe

benmore99
la source
2

Eh bien, si vous ne voulez pas changer vos nibs et afficher la hiérarchie comme l'a suggéré David C., cette méthode le fera pour vous. Pour ajouter des coins arrondis et des ombres à votre UIImageView, utilisez simplement cette méthode, par exemple:

[Utils roundCornersForImageView:myImageView withCornerRadius:6.0 
andShadowOffset:2.0];

(!) Pour des raisons de performances, je ne pense pas que ce soit une bonne idée d'utiliser ce code dans quelque chose comme UITableView, car ce code change la hiérarchie des vues. Je proposerai donc de changer votre plume et d'ajouter une vue de conteneur pour l'effet d'ombre et d'utiliser le code Davic C..

+ (void)roundCornersForImageView:(UIImageView *)imageView 
withCornerRadius:(float)cornerRadius andShadowOffset:(float)shadowOffset
{
    const float CORNER_RADIUS = cornerRadius;
    const float BORDER_WIDTH = 1.0; 
    const float SHADOW_OFFSET = shadowOffset;
    const float SHADOW_OPACITY = 0.8;
    const float SHADOW_RADIUS = 3.0;

    //Our old image now is just background image view with shadow
    UIImageView *backgroundImageView = imageView;
    UIView *superView = backgroundImageView.superview;

    //Make wider actual visible rect taking into account shadow
    //offset
    CGRect oldBackgroundFrame = backgroundImageView.frame;
    CGRect newBackgroundFrame = CGRectMake(oldBackgroundFrame.origin.x, oldBackgroundFrame.origin.y, oldBackgroundFrame.size.width + SHADOW_OFFSET, oldBackgroundFrame.size.height + SHADOW_OFFSET);
    [backgroundImageView removeFromSuperview];
    backgroundImageView.frame = newBackgroundFrame;        

    //Make new UIImageView with rounded corners and put our old image
    CGRect frameForRoundedImageView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
    UIImageView *roundedImageView = [[UIImageView alloc]initWithFrame:frameForRoundedImageView];
    roundedImageView.image = imageView.image;
    [roundedImageView.layer setCornerRadius:CORNER_RADIUS];
    [roundedImageView.layer setBorderColor:[UIColor lightGrayColor].CGColor];        
    [roundedImageView.layer setBorderWidth:BORDER_WIDTH]; 
    [roundedImageView.layer setMasksToBounds:YES];

    //Set shadow preferences
    [backgroundImageView setImage:nil];
    [backgroundImageView.layer setShadowColor:[UIColor blackColor].CGColor];
    [backgroundImageView.layer setShadowOpacity:SHADOW_OPACITY];
    [backgroundImageView.layer setShadowRadius:SHADOW_RADIUS];
    [backgroundImageView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];   

    //Add out two image views back to the view hierarchy.
    [backgroundImageView addSubview:roundedImageView];
    [superView addSubview:backgroundImageView];   
}    
Roman Minenok
la source
2

Ancien fil toujours actuel ...

J'ai édité la méthode de Daniel Gindi pour pouvoir l'utiliser également avec des boutons etc. Si quelqu'un a besoin de coins arrondis ou souhaite combiner des coins arrondis et une bordure, il doit être défini sur le calque de la vue qui est transmis à cette méthode. J'ai également réglé la pixellisation pour l'accélérer un peu.

+ (UIView*)putView:(UIView*)view insideShadowWithColor:(CGColorRef)color 
                                 andRadius:(CGFloat)shadowRadius 
                                 andOffset:(CGSize)shadowOffset 
                                 andOpacity:(CGFloat)shadowOpacity
{
    // Must have same position like "view"
    UIView *shadow = [[UIView alloc] initWithFrame:view.frame]; 

    shadow.layer.contentsScale = [UIScreen mainScreen].scale;
    shadow.userInteractionEnabled = YES; // Modify this if needed
    shadow.layer.shadowColor = color;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    shadow.layer.rasterizationScale = [UIScreen mainScreen].scale;
    shadow.layer.shouldRasterize = YES;

    [view.superview insertSubview:shadow belowSubview:view];
    [shadow addSubview:view];

    // Move view to the top left corner inside the shadowview 
    // ---> Buttons etc are working again :)
    view.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);

    return shadow;
}
NickBln
la source
2

Ce qui a fonctionné le mieux pour moi (ce code réside dans l'extension UIView, donc self dénote une certaine UIView à laquelle nous devons ajouter une ombre et un coin rond)

- (void)addShadowViewWithCornerRadius:(CGFloat)radius {

UIView *container = self.superview;

if (!container) {
    return;
}

UIView *shadowView = [[UIView alloc] init];
shadowView.translatesAutoresizingMaskIntoConstraints = NO;
shadowView.backgroundColor = [UIColor lightGrayColor];
shadowView.layer.cornerRadius = radius;
shadowView.layer.masksToBounds = YES;

[container addSubview:shadowView];
[container bringSubviewToFront:shadowView];

[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeWidth
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeWidth
                                                     multiplier:1.0
                                                       constant:0.0]];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeLeading
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeLeading
                                                     multiplier:1.0
                                                       constant:2.0]];

[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeHeight
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeHeight
                                                     multiplier:1.0
                                                       constant:0.0]];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeTop
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeTop
                                                     multiplier:1.0
                                                       constant:2.0]];
[container sendSubviewToBack:shadowView];
}

La principale différence entre cet exemple et d'autres exemples de code est que cela ajoute la vue d'ombre en tant que vue sœur (par opposition à l'ajout de la vue actuelle en tant que sous-vue de la vue d'ombre), éliminant ainsi la nécessité de modifier la hiérarchie de vue existante de quelque manière que ce soit.

Mehul Parmar
la source
1

La réponse de daniel.gindi ci-dessus a fait l'affaire pour moi! (+1 daniel) Cependant, j'ai dû faire des ajustements mineurs - changer la taille de shadowFrame pour qu'elle soit identique à la taille du cadre de la vue et permettre l'interaction avec l'utilisateur. Voici le code mis à jour:

+ (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
    CGRect shadowFrame; // Modify this if needed

    // Modified this line
    shadowFrame.size = CGSizeMake(view.frame.size.width, view.frame.size.height);

    shadowFrame.origin.x = 0.f;
    shadowFrame.origin.y = 0.f;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];

    // Modified this line
    shadow.userInteractionEnabled = YES;
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;

    [shadow addSubview:view];
    return shadow;
}

Je voudrais ajouter que dans mon cas, j'essayais d'ajouter ceci à un contrôleur de vue tiers, c'est-à-dire que je n'avais pas de contrôle direct sur le code. Alors, voici comment j'ai utilisé la fonction ci-dessus:

UIView *shadow = [self putView:vc.view 
         insideShadowWithColor:[UIColor blackColor]
                     andRadius:5.0 
                     andOffset:CGSizeMake(0.0, 0.0) 
                    andOpacity:1.0];
vc.view = shadow;
vc.view.layer.cornerRadius = 5.0;
vc.view.layer.masksToBounds = YES;
Digitrance
la source
1

J'apporte quelques modifications au code de daniel.gindi

C'est tout ce dont vous avez besoin pour le faire fonctionner.

+ (void)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andBlur:         (CGFloat)blur andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
    CGRect shadowFrame = view.frame;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
    shadow.backgroundColor = [UIColor redColor];
    shadow.userInteractionEnabled = YES; // Modify this if needed
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = blur;
    shadow.layer.cornerRadius = view.layer.cornerRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    [view.superview insertSubview:shadow belowSubview:view];
}
Carlos López
la source
1

Vous devez en utiliser deux UIViewspour y parvenir. L'un UIViewfonctionnera comme l'ombre et l'autre fonctionnera pour une bordure arrondie.

Voici un extrait de code a Class Methodavec l'aide de a protocol:

@implementation UIMethods

+ (UIView *)genComposeButton:(UIViewController <UIComposeButtonDelegate> *)observer;
{
    UIView *shadow = [[UIView alloc]init];
    shadow.layer.cornerRadius = 5.0;
    shadow.layer.shadowColor = [[UIColor blackColor] CGColor];
    shadow.layer.shadowOpacity = 1.0;
    shadow.layer.shadowRadius = 10.0;
    shadow.layer.shadowOffset = CGSizeMake(0.0f, -0.5f);

    UIButton *btnCompose = [[UIButton alloc]initWithFrame:CGRectMake(0, 0,60, 60)];
    [btnCompose setUserInteractionEnabled:YES];
    btnCompose.layer.cornerRadius = 30;
    btnCompose.layer.masksToBounds = YES;
    [btnCompose setImage:[UIImage imageNamed:@"60x60"] forState:UIControlStateNormal];
    [btnCompose addTarget:observer action:@selector(btnCompose_click:) forControlEvents:UIControlEventTouchUpInside];
    [shadow addSubview:btnCompose];
    return shadow;
}

Dans le code ci btnCompose_click:- dessus deviendra une @requiredméthode déléguée qui se déclenchera sur le clic du bouton.

Et ici, j'ai ajouté un bouton à mon UIViewControllercomme ceci:

UIView *btnCompose = [UIMethods genComposeButton:self];
btnCompose.frame = CGRectMake(self.view.frame.size.width - 75,
                          self.view.frame.size.height - 75,
                          60, 60);
[self.view addSubview:btnCompose];

Le résultat ressemblera à ceci:

entrez la description de l'image ici

Vaibhav Saran
la source
1

J'ai essayé tant de solutions de ce post et je me suis retrouvé avec la solution ci-dessous. Il s'agit d' une solution à l' épreuve complète, sauf si vous devez déposer une ombre sur une vue en couleur claire .

- (void)addShadowWithRadius:(CGFloat)shadowRadius withOpacity:(CGFloat)shadowOpacity withOffset:(CGSize)shadowOffset withColor:(UIColor *)shadowColor withCornerradius:(CGFloat)cornerRadius
{
    UIView *viewShadow = [[UIView alloc]initWithFrame:self.frame];
    viewShadow.backgroundColor = [UIColor whiteColor];
    viewShadow.layer.shadowColor = shadowColor.CGColor;
    viewShadow.layer.shadowOffset = shadowOffset;
    viewShadow.layer.shadowRadius = shadowRadius;
    viewShadow.layer.shadowOpacity = shadowOpacity;
    viewShadow.layer.cornerRadius = cornerRadius;
    viewShadow.layer.masksToBounds = NO;
    [self.superview insertSubview:viewShadow belowSubview:self];

    [viewShadow setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];
    [self layoutIfNeeded];

    self.layer.cornerRadius = cornerRadius;
    self.layer.masksToBounds = YES;
}
Mahesh Agrawal
la source
L'expression est "infaillible". :)
Ben Thomas
Je corrigeais juste l'anglais. :) La solution fonctionne.
Ben Thomas
1

Voici la solution qui fonctionnera à coup sûr!

J'ai créé l'extension UIView avec les bords requis pour appliquer l'ombre comme ci-dessous


enum AIEdge:Int {
    case
    Top,
    Left,
    Bottom,
    Right,
    Top_Left,
    Top_Right,
    Bottom_Left,
    Bottom_Right,
    All,
    None
}

extension UIView {

    func applyShadowWithCornerRadius(color:UIColor, opacity:Float, radius: CGFloat, edge:AIEdge, shadowSpace:CGFloat)    {

        var sizeOffset:CGSize = CGSize.zero

        switch edge {
        case .Top:
            sizeOffset = CGSize(width: 0, height: -shadowSpace)
        case .Left:
            sizeOffset = CGSize(width: -shadowSpace, height: 0)
        case .Bottom:
            sizeOffset = CGSize(width: 0, height: shadowSpace)
        case .Right:
            sizeOffset = CGSize(width: shadowSpace, height: 0)


        case .Top_Left:
            sizeOffset = CGSize(width: -shadowSpace, height: -shadowSpace)
        case .Top_Right:
            sizeOffset = CGSize(width: shadowSpace, height: -shadowSpace)
        case .Bottom_Left:
            sizeOffset = CGSize(width: -shadowSpace, height: shadowSpace)
        case .Bottom_Right:
            sizeOffset = CGSize(width: shadowSpace, height: shadowSpace)


        case .All:
            sizeOffset = CGSize(width: 0, height: 0)
        case .None:
            sizeOffset = CGSize.zero
        }

        self.layer.cornerRadius = self.frame.size.height / 2
        self.layer.masksToBounds = true;

        self.layer.shadowColor = color.cgColor
        self.layer.shadowOpacity = opacity
        self.layer.shadowOffset = sizeOffset
        self.layer.shadowRadius = radius
        self.layer.masksToBounds = false

        self.layer.shadowPath = UIBezierPath(roundedRect:self.bounds, cornerRadius:self.layer.cornerRadius).cgPath
    }
}

Enfin, vous pouvez appeler la fonction shadow comme ci-dessous pour n'importe laquelle de votre sous-classe UIView, vous pouvez également spécifier le bord sur lequel appliquer l'ombre, essayez différentes variantes selon vos besoins en modifiant les paramètres de l'appel de méthode ci-dessous.

viewRoundedToBeShadowedAsWell.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)

Image de résultat

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

Dhaval H. Nena
la source
0

La réponse fournie par Evan Mulawski fonctionnera parfaitement. Le hic est que vous devez définir la couleur d'arrière-plan de la vue sur clearColor et la propriété masksToBounds sur NO.

Vous pouvez définir la couleur de votre choix pour la vue, la définir comme

v.layer.backgroundColor = your color;

J'espère que cela t'aides..

Abdur Rahman
la source
0

Voici comment vous le faites, avec des coins arrondis et des ombres arrondies sans vous soucier des chemins.

//Inner view with content
[imageView.layer setBorderColor:[[UIColor lightGrayColor] CGColor]];
[imageView.layer setBorderWidth:1.0f];
[imageView.layer setCornerRadius:8.0f];
[imageView.layer setMasksToBounds:YES];

//Outer view with shadow
UIView* shadowContainer = [[UIView alloc] initWithFrame:imageView.frame];
[shadowContainer.layer setMasksToBounds:NO];
[shadowContainer.layer setShadowColor:[[UIColor blackColor] CGColor]];
[shadowContainer.layer setShadowOpacity:0.6f];
[shadowContainer.layer setShadowRadius:2.0f];
[shadowContainer.layer setShadowOffset: CGSizeMake(0.0f, 2.0f)];

[shadowContainer addSubview:imageView];

La vue avec contenu, dans mon cas une UIImageView, a un rayon d'angle et doit donc masquer les limites.

Nous créons une autre vue de taille égale pour les ombres, définissons son maskToBounds sur NO, puis ajoutons la vue de contenu à la vue du conteneur (par exemple shadowContainer).

Ford Davis
la source
0

J'écris cette méthode de catégorie UIView pour résoudre ce problème, utilise des vues distinctes pour l'ombre et le rayon d'angle.

-(UIView *)shadowedWrapViewWithBounds:(CGRect)bounds {
UIView *baseView = [[UIView alloc] init];
baseView.bounds = bounds;
baseView.backgroundColor = [UIColor clearColor];
baseView.layer.shadowColor = [UIColor blackColor].CGColor;
baseView.layer.shadowOffset = CGSizeMake(0, 0);
baseView.layer.shadowOpacity = 0.7;
baseView.layer.shadowRadius = 4.0;

// improve performance
baseView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:baseView.bounds cornerRadius:4].CGPath;
baseView.layer.shouldRasterize = YES;
baseView.layer.rasterizationScale = [UIScreen mainScreen].scale;

[baseView addSubview:self];
//use Masonry autolayout, self can set corner radius
[self makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(baseView);
}];

return baseView;
}
Liu Chao
la source
0

Swift 4 Solution pour rendre UICollectionViewCell ronde et ajouter des ombres , sans extensions ni complications :)

Remarque: pour les vues simples, par exemple les boutons. Voir la réponse de @ suragch dans cet article. https://stackoverflow.com/a/34984063/7698092 . Testé avec succès pour les boutons

Au cas où quelqu'un aurait encore du mal à contourner les coins et à ajouter des ombres en même temps. Bien que cette solution fonctionne avec UICollectionViewCell, elle peut être généralisée à n'importe quelle vue.

Cette technique a fonctionné pour moi sans faire d'extensions et toutes les choses compliquées. Je travaille avec storyBoard.

Technique

Vous devez ajouter une UIView (disons "containerView") à l'intérieur de votre UICollectionViewCell dans storyBoard et ajouter toutes les vues requises (boutons, images, etc.) à l'intérieur de cette containerView. Voir la capture d'écran. Structure de la cellule

Connectez la sortie pour containerView. Ajoutez les lignes de code suivantes dans la fonction déléguée CellforItemAtIndexPath.

//adds shadow to the layer of cell

cell.layer.cornerRadius = 3.0
    cell.layer.masksToBounds = false
    cell.layer.shadowColor = UIColor.black.cgColor
    cell.layer.shadowOffset = CGSize(width: 0, height: 0)
    cell.layer.shadowOpacity = 0.6

//makes the cell round 

let containerView = cell.containerView!
    containerView.layer.cornerRadius = 8
    containerView.clipsToBounds = true

Production

Voir la capture d'écran du simulateur Coins arrondis avec ombres (UICollectionViewCell)

Awais Fayyaz
la source
0
extension UIView {
    func dropRoundedShadowForAllSides() {
        let backgroundView = UIView(frame:self.frame)
        let radius = frame.height/2
        backgroundView.layer.masksToBounds = false
        self.layer.masksToBounds = true
        backgroundView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        backgroundView.layer.shadowRadius = 4
        backgroundView.layer.shadowOpacity = 0.4

        let path = UIBezierPath()

        // Start at the Top Left Corner + radius distance
        path.move(to: CGPoint(x: 2*radius, y: 0.0))

        // Move to the Top Right Corner - radius distance
        path.addLine(to: CGPoint(x: backgroundView.frame.size.width - radius, y: 0.0))

        // Move to top right corner + radius down as curve
        let centerPoint1 = CGPoint(x:backgroundView.frame.size.width - radius,y:radius)
        path.addArc(withCenter: centerPoint1, radius: radius, startAngle: 3*(.pi/2), endAngle: 0, clockwise: true)

        // Move to the Bottom Right Corner - radius
        path.addLine(to: CGPoint(x: backgroundView.frame.size.width, y: backgroundView.frame.size.height - radius))

        // Move to top right corner + radius left as curve
        let centerPoint2 = CGPoint(x:backgroundView.frame.size.width - radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint2, radius: radius, startAngle: 0, endAngle: .pi/2, clockwise: true)

        // Move to the Bottom Left Corner - radius
        path.addLine(to: CGPoint(x: radius, y: backgroundView.frame.size.height))

        // Move to left right corner - radius up as curve
        let centerPoint3 = CGPoint(x:radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint3, radius: radius, startAngle: .pi/2, endAngle: .pi, clockwise: true)

        // Move to the top Left Corner - radius
        path.addLine(to: CGPoint(x: 0, y: radius))

        // Move to top right corner + radius down as curve
        let centerPoint4 = CGPoint(x:radius,y:radius)
        path.addArc(withCenter: centerPoint4, radius: radius, startAngle: .pi, endAngle: 3 * (.pi/2), clockwise: true)

        path.close()

        backgroundView.layer.shadowPath = path.cgPath
        if let superView = self.superview {
            superView.addSubview(backgroundView)
            superView.sendSubview(toBack: backgroundView)
            superView.bringSubview(toFront: self)
        }

    }
}
jeevan eashwar
la source
Bonjour, merci pour votre réponse, vous devez ajouter quelques commentaires à votre code pour expliquer un peu comme décrit dans Comment répondre .
Baptiste Mille-Mathias