UIView com cantos arredondados e sombra projetada?

390

Eu quero um costume UIView...: eu só queria uma visualização em branco em branco com cantos arredondados e uma sombra clara (sem efeito de iluminação). Eu posso fazer cada um um por um, mas os habituais clipToBounds/ maskToBoundsconflitos ocorrem.

Aditya Vaidyam
fonte
11
Como você disse em um comentário abaixo que conseguiu isso usando o CoreGraphics, você se importaria em compartilhar a resposta com a comunidade para poder ajudar outras pessoas na mesma situação, enquanto tentavam ajudá-lo?
lnafziger
Sinto muito, isso foi há muito tempo e eu não tenho mais a fonte. O que fiz foi substituir -drawRect: e usar UIBezierPath para desenhar um retângulo e aplicar uma sombra à camada que está apoiando a exibição ... se bem me lembro. :)
Aditya Vaidyam
5
A resposta aceita não funciona!
onmyway133
11
Possível duplicado de Dar UIView cantos arredondados
11
@ Sachavijay Você deve verificar as datas de ambas as postagens antes de comentar.
Aditya Vaidyam

Respostas:

444

O seguinte snippet de código adiciona uma borda, raio da borda e sombra projetada a 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)];

Você pode ajustar as configurações para atender às suas necessidades.

Além disso, adicione a estrutura QuartzCore ao seu projeto e:

#import <QuartzCore/QuartzCore.h>

Veja minha outra resposta sobre masksToBounds.


Nota

Isso pode não funcionar em todos os casos. Se você achar que esse método interfere com outras operações de desenho que você está executando, consulte esta resposta .

Evan Mulawski
fonte
83
Bem, o problema com ele é que quando eu definir raio de canto, ele define maskToBounds: SIM, enquanto que a sombra requer ClipToBounds: NÃO (onde ClipToBounds faz o mesmo que maskToBounds)
Aditya Vaidyam
15
mesmo problema aqui. Se eu tiver uma cor de fundo, quero que ela seja cortada nos cantos arredondados. Para fazer isso eu tenho que usar maskToBounds = TRUE, mas depois o dissapears sombra ..
hfossli
3
Para iniciantes como eu: tive que importar a estrutura QuartzCore para o meu projeto para chamar métodos no objeto de camada.
SilithCrowe 27/01
38
A maneira de fazer com que isso funcione da maneira correta é usar uma exibição de contêiner interno, que abrigará a borda e a cor do plano de fundo, ambas com um raio de canto. Essa visualização será cortada até o limite! A segunda visualização do contêiner externo abrigará a primeira, tem o mesmo quadro, com apenas uma sombra projetada. Fiz isso várias vezes para combinar uma borda, sombra projetada e raio de canto. É realmente irritante, mas funciona muito bem.
precisa saber é o seguinte
23
Não funciona Não faço ideia por que existem tantos votos positivos. Isso foi aplicável em versões mais antigas?
Yarneo 27/05
628

Rápido

insira a descrição da imagem aqui

// 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

Explorando as opções

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Problema 1: a sombra é cortada

E se houver subcamadas ou subvisões (como uma imagem) cujo conteúdo queremos recortar nos limites de nossa visão?

insira a descrição da imagem aqui

Podemos conseguir isso com

blueView.layer.masksToBounds = true

(Como alternativa, blueView.clipsToBounds = truefornece o mesmo resultado .)

insira a descrição da imagem aqui

Mas oh não! A sombra também foi cortada porque está fora dos limites! O que fazer? O que fazer?

Solução

Use vistas separadas para a sombra e a borda. A vista base é transparente e tem a sombra. A vista de borda recorta qualquer outro subcontente que possui em suas bordas.

// 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)

Isso fornece o seguinte resultado:

insira a descrição da imagem aqui

Problema 2: Baixo desempenho

Adicionar cantos e sombras arredondados pode ser um sucesso. Você pode melhorar o desempenho usando um caminho predefinido para a sombra e também especificando que ela seja rasterizada. O código a seguir pode ser adicionado ao exemplo acima.

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

Veja este post para mais detalhes. Veja aqui e aqui também.

Esta resposta foi testada com Swift 4 e Xcode 9.

Suragch
fonte
11
@ EICaptainv2.0, se você deseja apenas uma borda (e / ou raio do canto), não precisa de uma visão separada. A visão separada é para a situação em que você precisa de cantos arredondados e sombra .
Suragch
2
Isso não está funcionando para mim. Quando defino a cor de fundo do terreno para limpar no baseView, uma sombra não aparece mais. O que estou fazendo errado?
Rutger Huijsmans
3
Não está funcionando, a configuração baseView.backgroundColor = UIColor.clearremove a sombra. Somente se você definir uma cor de fundo, você a verá.
Aleksander
2
NÃO FUNCIONA PARA MIM.
Markus
4
Para sua informação, eu estava inicialmente vendo o mesmo problema que outros comentaristas estavam vendo onde a sombra do baseView não era exibida quando a cor do plano de fundo era clara. O problema era que eu estava executando apenas a primeira parte do código (o material baseView). Depois de adicionar o borderView como uma subvisão, a sombra começou a ser exibida. Parece que, para que a sombra seja exibida, deve haver pelo menos uma borda visível (ou plano de fundo) na hierarquia de visualizações. Então não se esqueça de ter borderView.layer.borderWidth> = 0 com um borderView.layer.borderColor não transparente (ou uma cor de fundo não transparente)
Mike Vosseller
79

Uma maneira de fazer isso é colocar a vista com cantos arredondados em uma vista com a sombra projetada.

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];

Em seguida, você pode adicionar o shadowView onde quiser.

David C.
fonte
5
Além disso, você deve definir maskToBounds / clipToBounds = YES para o * roundedView only *. NÃO defina isso para o shadowView. Eu não tentei o código acima, mas tenho certeza de que esta solução definitivamente funciona, embora não seja o ideal. O shadowRadius mais alto cuida das áreas do raio dos cantos. Defina o shadowRadius como 0 ou 1 e você perceberá o que estou tentando dizer.
Deepak GM
2
Algo como shadowView.layer.shadowOpacity = 0.6; está faltando
Bo.
3
"shadowView.layer.opacity = 1.0" deve ser "shadowView.layer.shadowOpacity = 1.0"
Chris
Funciona no iOS 9 se usar shadowView.layer.shadowOpacity = 1.0 #
Mansurov Ruslan
Código corrigido para shadowOpacity
Softlion
63

Confira o projeto de exemplo no GitHub para garantir que você use o componente corretamente.

Solução simples do Swift 5 sem subvisões ou subclasses adicionais:

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

Observe que você deve configurar sua exibição com raio de canto e outras propriedades antes de ligar addShadow .

Depois disso, basta chamar viewDidLoadassim:

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

Resultado final:

resultado

Super fácil e simples!

Sergey Grischyov
fonte
Isso funciona nos botões? Porque não está funcionando do meu lado.
Cesare
Tentei seguir as etapas exatas que você sugeriu. Mas ainda sem sorte. Seria ótimo se você compartilhar uma amostra (no Github) para ver como você fez o que parece impossível para mim e para outras pessoas.
precisa saber é o seguinte
Conseguiu fazê-lo funcionar apenas removendo esta linha layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath. Não posso explicar por que, porém, alguém tem uma explicação para isso?
Trupin
O @Curnelious está à vontade para dar uma olhada na resposta atualizada com um exemplo de projeto do Xcode. Não pode não funcionar :)
Sergey Grischyov
3
Isso funcionou para mim também, só preciso de uma coisa a mais para fazer com que todas as subvisões sejam exibidas em cores claras, para que apenas a exibição do contêiner tenha um fundo visível e isso resolva o meu problema. Obrigado!! @SergeyGrischyov
Rishabh
42

Isso funcionou para mim. O truque era mover a cor do plano de fundo da vista principal para a camada.

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
fonte
Embora todas as outras soluções funcionem, e talvez sejam mais gerais, essa é de longe a melhor solução para o problema. A adição de subvisões ou subcamadas cria um mundo ou dor ao tentar manter o tamanho dos quadros ou, na melhor das hipóteses, pode causar problemas de desempenho.
EMEM
Essa deve ser a resposta. Limpo e elegante.
Axy
Melhor solução e definitivamente elegante!
Roberto Ferraz
Uau, isso realmente funciona. Eu não entendo por que ele deve funcionar - você acha que o backgroundColor da exibição seria mapeado diretamente diretamente para a propriedade layer.backgroundColor no iOS - mas funciona. (Xcode 8, Swift 3.) Muito bem, e obrigado. Essa deve ser a resposta aceita.
Womble 27/02
Eu criei uma versão Swift 3.1 da sua resposta usando UIView extensionaqui - stackoverflow.com/a/43295741/1313939 obrigado pela inspiração!
Sergey Grischyov 08/04
26

Resolvi o problema usando o seguinte truque ao atribuir o caminho da sombra para a exibição do contêiner:

[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]

Observe que o caminho dado à sombra é um retângulo arredondado com o mesmo raio de canto do plano de fundo que a célula contém:

//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
fonte
A melhor resposta, porque explica a maneira correta de adicionar sombra a uma vista de canto mais arredondada. Obrigado @Alex Stone
programador
17

Se você está lutando por causa do arredondado cornersvs. subviewsvs. masksToBounds, tente usar minha função:

- (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;
}

chame na sua opinião. se sua vista possui cantos arredondados, não importa seu tamanho, sua forma - uma bela sombra será desenhada.

Apenas mantenha o valor de retorno da função para poder consultá-la quando desejar remover a tabela (ou, por exemplo, usar insertSubview:aboveView:)

daniel.gindi
fonte
Funciona bem. Mas se a visão tiver reconhecedores de gestos, ela não funcionará. como podemos resolver isso?
Manujmv #
@manujmv Você vê as linhas em que "// Modifique isso, se necessário" está especificado? É disso que você precisa. shadow.userInteractionEnabled = SIM;
Daniel.gindi
@manujmv, então você deve testar os quadros da visualização e subview para saber o porquê. algo provavelmente não está bem ali. este código exato funciona para mim em algumas muito agradáveis aplicativos
daniel.gindi
2
Esta solução funciona muito bem para UITableViews com cantos arredondados. Gostaria de poder dar mais votos. Obrigado!
Chris Hart
@ CarlosEduardoLópez Você vê a shadow.userInteractionEnabled = NO; // Modify this if neededlinha? Portanto, este é o caso quando necessário. userInteractionEnabledé uma propriedade básica e popular você deve já estar familiarizado com :-)
daniel.gindi
12

Usando o Swift 4 e o Xcode 9 , este é um exemplo prático de arredondar um ImageViewcom uma sombra projetada e uma borda.

    //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)

insira a descrição da imagem aqui

Se você deseja que a imagem seja circular: (e mostrada sem borda)

let cornerRadius = imageWidth / 2

insira a descrição da imagem aqui

rbaldwin
fonte
7

Eu criei um ajudante no UIView

@interface UIView (Helper)

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

você pode chamar assim

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

Aqui está a implementação

- (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
fonte
2
Esta é uma boa solução elegante. Verifique se a sua visão foi adicionada à sua visão geral antes de usar. Eu adicionei alguns parâmetros para me dar mais controle sobre a sombra, mas no geral funciona perfeito. Obrigado!
quer
Isso é bom solução, mas ele não funciona com autolayout: a vista vai ser desenhado em origem 0,0
gderaco
5

Depois de um dia inteiro pesquisando a vista do canto redondo com sombra, fico feliz em postar minha classe de uiview personalizada aqui, e espero terminar esta pergunta:

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

portanto, NÃO é necessário adicionar subvisão na vista ou abaixo na visualização de destino, basta adicionar uma camada na visualização atual e fazer 3 etapas para concluí-la!

observe atentamente os comentários no código; é útil entender o componente!

lwz7512
fonte
5

Algo swifty testado no 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
        }
    }
}

Produz

insira a descrição da imagem aqui

Se você ativá-lo no Inspetor desta forma:

insira a descrição da imagem aqui

Ele adicionará o atributo de tempo de execução definido pelo usuário, resultando em:

insira a descrição da imagem aqui

(Eu adicionei anteriormente o cornerRadius = 8)

:)

dGambit
fonte
5

Você precisa usar shadowVieweroundView

insira a descrição da imagem aqui

shadowView

  • Deve ter cor de fundo
  • Deve ficar para trás roundView
  • O truque é fazer shadowViewum layout interno, e sua sombra precisa brilhar. Ajuste o botão insetspara que shadowViewfique completamente invisível atrásroundView

roundView

  • Clips obrigatórios subvisões

O código

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 você pode fazer abaixo sem especificar clipToBounds/maskToBounds

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

Solução Swift 3 e IBInspectable:
Inspirada na solução da Ade

Primeiro, crie uma extensão 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
          }
     }
}

Em seguida, basta selecionar o UIView no construtor de interface, definindo a sombra LIGADA e o raio do canto , como abaixo:

Selecionando seu UIView

Ativando a sombra e o raio do canto

O resultado!

Resultado

Thomás Calmon
fonte
Como todas as outras "soluções" deste segmento, ele simplesmente não funciona, pelo menos não no iOS 11.0 / Swift 4.1.
inexcitus
Você leu "Swift 3" no início do tópico? Então, isso significa que é uma solução Swift 3, não testei no Swift 4.1 porque não preciso mais. Sinta-se livre para editar a resposta e dar uma solução. ;) Cheers
Thomás Calmon
3

Aqui está a solução para o problema de conflito do masksToBounds, funciona para mim.

Depois de definir o corderRadius / borderColor / shadow e assim por diante, defina masksToBounds como NO:

v.layer.masksToBounds = NO;
Shaopeng Wang
fonte
Isso funcionou para mim !! omg eu quase fiz todos os truques acima, você responde! obrigado Shaopeng.
MontDeska
3

Sombra + borda + raio do canto insira a descrição da imagem aqui

    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
fonte
3

Aqui está a minha versão no Swift 3 para um 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
fonte
3

Swift 4: Criar subclasse do 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
    }

}

Usando ..

Usar vista de sombra de classe

benmore99
fonte
2

Bem, se você não deseja alterar suas pontas e visualizar a hierarquia como sugerido por David C., esse método fará isso por você. Para adicionar cantos arredondados e sombra ao seu UIImageView, use este método, por exemplo:

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

(!) Por motivos de desempenho, acho que não é uma boa ideia usar esse código em algo como UITableView, pois esse código altera a hierarquia de exibição. Então, sugiro alterar sua ponta e adicionar uma exibição de contêiner para efeito de sombra e usar o código 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
fonte
2

Tópico antigo ainda atual ...

Eu editei o método de Daniel Gindi para tornar possível usá-lo também com botões etc. Se alguém precisar de cantos arredondados ou quiser combinar cantos arredondados e uma borda, ele deverá ser definido na camada da vista que é passada para esse método. Também configurei a rasterização para acelerar um pouco.

+ (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
fonte
2

O seguinte funcionou melhor para mim (esse código está na extensão UIView, portanto, denota um UIView ao qual devemos adicionar uma sombra e um canto redondo)

- (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];
}

A principal diferença entre esse e outros exemplos de código é que isso adiciona a visualização de sombra como uma visão secundária (contra a adição da visualização atual como subvisão da visualização de sombra), eliminando assim a necessidade de modificar a hierarquia de visualização existente de qualquer maneira.

Mehul Parmar
fonte
1

A resposta de daniel.gindi acima fez o truque para mim! (+1 daniel) No entanto, tive que fazer pequenos ajustes - alterar o tamanho do shadowFrame para que seja o mesmo do tamanho do quadro da visualização e permitir a interação do usuário. Aqui está o código atualizado:

+ (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;
}

Gostaria de acrescentar que, no meu caso, estava tentando adicionar isso a um controlador de exibição de terceiros, ou seja, não tinha controle direto sobre o código. Então, aqui está como eu usei a função acima:

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
fonte
1

Eu faço algumas alterações no código de daniel.gindi

É tudo o que você precisa para fazer funcionar.

+ (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
fonte
1

Você precisa usar dois UIViewspara conseguir isso. Um UIViewfuncionará como sombra e outro funcionará para bordas arredondadas.

Aqui está um trecho de código a Class Methodcom a ajuda 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;
}

No código acima, btnCompose_click:ele se tornará um @requiredmétodo delegado que será acionado no clique do botão.

E aqui eu adicionei um botão ao meu UIViewControllerassim:

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];

O resultado será semelhante a este:

insira a descrição da imagem aqui

Vaibhav Saran
fonte
1

Eu tentei muitas soluções neste post e acabei com a solução abaixo. Esta é uma solução completa , a menos que você precise soltar sombras em uma exibição de cores nítidas .

- (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
fonte
A expressão é "à prova de idiotas". :)
Ben Thomas
Eu estava apenas corrigindo o inglês. :) A solução funciona.
21718 Ben Thomas
1

Aqui está a solução que funcionará com certeza!

Eu criei a extensão UIView com as bordas necessárias para aplicar a sombra como abaixo


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

Por fim, você pode chamar a função de sombra como abaixo para qualquer subclasse do UIView, também pode especificar a borda para aplicar a sombra, experimentar variações diferentes conforme a necessidade de alterar os parâmetros da chamada de método abaixo.

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

Imagem de resultado

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Dhaval H. Nena
fonte
0

A resposta fornecida por Evan Mulawski funcionará perfeitamente. O problema é que você precisa definir a cor de plano de fundo para a exibição clearColor e a propriedade masksToBounds como NO.

Você pode definir a cor que desejar para a vista, definir como

v.layer.backgroundColor = your color;

Espero que isto ajude..

Abdur Rahman
fonte
0

É assim que você faz, com cantos arredondados e sombras arredondadas sem se preocupar com caminhos.

//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];

A exibição com conteúdo, no meu caso, um UIImageView, tem um raio de canto e, portanto, tem que mascarar até os limites.

Criamos outra visualização de tamanho igual para as sombras, configuramos maskToBounds como NO e adicionamos a visualização de conteúdo à visualização do contêiner (por exemplo, shadowContainer).

Ford Davis
fonte
0

Eu escrevo esse método de categoria UIView para resolver esse problema, usa visualizações separadas para a sombra e o raio do canto.

-(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
fonte
0

Swift 4 Solução para fazer UICollectionViewCell rodada e adicionando sombras , sem quaisquer extensões e complicações :)

Nota: Para visualizações simples, por exemplo, botões. Veja a resposta do @ suragch neste post. https://stackoverflow.com/a/34984063/7698092 . Testado com sucesso para botões

Caso alguém ainda esteja lutando para virar as esquinas e adicionar sombras ao mesmo tempo. Embora esta solução funcione com o UICollectionViewCell, ela pode ser generalizada para qualquer visualização.

Essa técnica funcionou para mim sem fazer nenhuma extensão e todas as coisas complicadas. Estou trabalhando com o storyBoard.

Técnica

Você deve adicionar um UIView (digamos "containerView") dentro do seu UICollectionViewCell no storyBoard e adicionar todas as visualizações necessárias (botões, imagens, etc.) dentro deste containerView. Veja a captura de tela. Estrutura da célula

Conecte a tomada para o containerView. Adicione as seguintes linhas de código na função delegada 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

Resultado

Veja o Screenshot do simulador Cantos arredondados com sombras (UICollectionViewCell)

Awais Fayyaz
fonte
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
fonte
Olá, obrigado pela resposta, você deve adicionar alguns comentários ao seu código para explicar um pouco, conforme descrito em Como responder .
Baptiste Mille-Mathias