Swift: problemas con el radio de la esquina y la sombra paralela

85

Estoy intentando crear un botón con esquinas redondeadas y una sombra paralela . No importa cómo lo cambie, el botón no se mostrará correctamente. Lo intenté masksToBounds = falsey masksToBounds = true, pero o el radio de la esquina funciona y la sombra no o la sombra funciona y el radio de la esquina no recorta las esquinas del botón.

import UIKit
import QuartzCore

@IBDesignable
class Button : UIButton
{
    @IBInspectable var masksToBounds: Bool    = false                {didSet{updateLayerProperties()}}
    @IBInspectable var cornerRadius : CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var borderWidth  : CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var borderColor  : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}}
    @IBInspectable var shadowColor  : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}}
    @IBInspectable var shadowOpacity: CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var shadowRadius : CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var shadowOffset : CGSize  = CGSizeMake(0, 0)     {didSet{updateLayerProperties()}}

    override func drawRect(rect: CGRect)
    {
        updateLayerProperties()
    }

    func updateLayerProperties()
    {
        self.layer.masksToBounds = masksToBounds
        self.layer.cornerRadius = cornerRadius
        self.layer.borderWidth = borderWidth
        self.layer.borderColor = borderColor.CGColor
        self.layer.shadowColor = shadowColor.CGColor
        self.layer.shadowOpacity = CFloat(shadowOpacity)
        self.layer.shadowRadius = shadowRadius
        self.layer.shadowOffset = shadowOffset
    }
}
Jake
fuente
Querrá poner la sombra y el recorte en diferentes capas. Y configurar las propiedades de la capa en drawRectno es una muy buena idea. Es mejor ponerlos initWithCoder.
David Berry
Solo para cualquiera que busque en Google aquí, como sucede a menudo con preguntas muy antiguas, la respuesta principal aquí, aunque generalmente es correcta ahora, tiene algunos errores críticos . (Puse una respuesta corregida). La mayoría de las personas, especialmente yo, copian y pegan ciegamente la respuesta SO superior: ¡tenga cuidado si es un QA muy antiguo ! (Es 2020 ahora, ¡alguien tendrá que reemplazar mi respuesta en 5 años!)
Fattie

Respuestas:

144

El siguiente código Swift 5 / iOS 12 muestra cómo establecer una subclase UIButtonque permite crear instancias con esquinas redondeadas y sombras a su alrededor:

import UIKit

final class CustomButton: UIButton {

    private var shadowLayer: CAShapeLayer!

    override func layoutSubviews() {
        super.layoutSubviews()

        if shadowLayer == nil {
            shadowLayer = CAShapeLayer()
            shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 12).cgPath
            shadowLayer.fillColor = UIColor.white.cgColor

            shadowLayer.shadowColor = UIColor.darkGray.cgColor
            shadowLayer.shadowPath = shadowLayer.path
            shadowLayer.shadowOffset = CGSize(width: 2.0, height: 2.0)
            shadowLayer.shadowOpacity = 0.8
            shadowLayer.shadowRadius = 2

            layer.insertSublayer(shadowLayer, at: 0)
            //layer.insertSublayer(shadowLayer, below: nil) // also works
        }        
    }

}

Según sus necesidades, puede agregar un UIButtonen su Storyboard y establecer su clase en CustomButtono puede crear una instancia de CustomButtonprogramáticamente. La siguiente UIViewControllerimplementación muestra cómo crear y usar una CustomButtoninstancia mediante programación:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = CustomButton(type: .system)
        button.setTitle("Button", for: .normal)
        view.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)        
        let widthConstraint = button.widthAnchor.constraint(equalToConstant: 100)
        let heightConstraint = button.heightAnchor.constraint(equalToConstant: 100)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
    }

}

El código anterior produce la siguiente imagen en el simulador de iPhone:

ingrese la descripción de la imagen aquí

Imanou Petit
fuente
con iOS tuve problemas con mi antigua implementación, ahora funciona. ¡Gracias!
carlodonz
1
¿Cómo se llama a la clase desde su controlador de vista principal @POB?
Lideró el
1
¿Hay alguna forma de recortar la capa de sombra, manteniendo solo la parte visible?
Johan Tingbacke
4
Dado que la capa de masksToBounds = YESsombra es una subcapa de la propia capa del botón, que debe mostrar esquinas redondeadas, ¿no se recortará también la sombra?
mattsson
3
Eso funciona bien, pero ya no puedo cambiar el fondo del botón. Esto probablemente se deba a shadowLayer.fillColor. ¿Que sugieres? Gracias !
GrayFox
34

Mi botón personalizado con algunas sombras y esquinas redondeadas , lo uso directamente dentro del Storyboardsin necesidad de tocarlo mediante programación.

Rápido 4

class RoundedButtonWithShadow: UIButton {
    override func awakeFromNib() {
        super.awakeFromNib()
        self.layer.masksToBounds = false
        self.layer.cornerRadius = self.frame.height/2
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.layer.cornerRadius).cgPath
        self.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
        self.layer.shadowOpacity = 0.5
        self.layer.shadowRadius = 1.0
    }
}

ingrese la descripción de la imagen aquí

alcance
fuente
Rapido y Facil.
Devbot10
1
Para mí funcionó cuando reemplacé el código en layoutSubviews().
Yash Bedi
14

Para ampliar la publicación de Imanou, es posible agregar mediante programación la capa de sombra en la clase de botón personalizado

@IBDesignable class CustomButton: UIButton {
    var shadowAdded: Bool = false

    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }

    override func drawRect(rect: CGRect) {
        super.drawRect(rect)

        if shadowAdded { return }
        shadowAdded = true

        let shadowLayer = UIView(frame: self.frame)
        shadowLayer.backgroundColor = UIColor.clearColor()
        shadowLayer.layer.shadowColor = UIColor.darkGrayColor().CGColor
        shadowLayer.layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: self.cornerRadius).CGPath
        shadowLayer.layer.shadowOffset = CGSize(width: 1.0, height: 1.0)
        shadowLayer.layer.shadowOpacity = 0.5
        shadowLayer.layer.shadowRadius = 1
        shadowLayer.layer.masksToBounds = true
        shadowLayer.clipsToBounds = false

        self.superview?.addSubview(shadowLayer)
        self.superview?.bringSubviewToFront(self)
    }
}
Matt Pinkston
fuente
2
Estás enmascarando la sombra de la capa y realmente no recomendaría poner la vista de sombra en la supervista del botón.
mattsson
13

Una forma alternativa de obtener un botón más utilizable y consistente.

Rápido 2:

func getImageWithColor(color: UIColor, size: CGSize, cornerRadius:CGFloat) -> UIImage {
    let rect = CGRectMake(0, 0, size.width, size.height)
    UIGraphicsBeginImageContextWithOptions(size, false, 1)
    UIBezierPath(
        roundedRect: rect,
        cornerRadius: cornerRadius
        ).addClip()
    color.setFill()
    UIRectFill(rect)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

let button = UIButton(type: .Custom)
button.frame = CGRectMake(20, 20, 200, 50)
button.setTitle("My Button", forState: UIControlState.Normal)
button.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
self.addSubview(button)

let image = getImageWithColor(UIColor.whiteColor(), size: button.frame.size, cornerRadius: 5)
button.setBackgroundImage(image, forState: UIControlState.Normal)

button.layer.shadowRadius = 5
button.layer.shadowColor = UIColor.blackColor().CGColor
button.layer.shadowOpacity = 0.5
button.layer.shadowOffset = CGSizeMake(0, 1)
button.layer.masksToBounds = false

Swift 3:

func getImageWithColor(_ color: UIColor, size: CGSize, cornerRadius:CGFloat) -> UIImage? {
    let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    color.setFill()
    UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).addClip()
    color.setFill()
    UIRectFill(rect)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}

let button = UIButton(type: .custom)
button.frame = CGRect(x:20, y:20, width:200, height:50)
button.setTitle("My Button", for: .normal)
button.setTitleColor(UIColor.black, for: .normal)
self.addSubview(button)

if let image = getImageWithColor(UIColor.white, size: button.frame.size, cornerRadius: 5) {
    button.setBackgroundImage(image, for: .normal)
}

button.layer.shadowRadius = 5
button.layer.shadowColor = UIColor.black.cgColor
button.layer.shadowOpacity = 0.5
button.layer.shadowOffset = CGSize(width:0, height:1)
button.layer.masksToBounds = false
aytek
fuente
1
Este método es el mejor ya que puede tener un color de fondo diferente para .normal y resaltado
Ryan Heitner
1
Agradable. Probé muchos métodos diferentes para hacer que el color de fondo, el radio de las esquinas y las sombras funcionaran en mis botones, ¡pero esta fue la única forma en que funcionó! ¡Gracias!
Harry Bloom
Esta es la solución perfecta, ¡gracias por esto! Una nota, si usa UIButton dentro de UITableViewCell, programáticamente, esto debe colocarse dentro de layoutSubviews ().
sujetador Escena
4

Refactoré esto para apoyar cualquier punto de vista. Subclasifique su vista de esto y debería tener esquinas redondeadas. Si agrega algo como un UIVisualEffectView como una subvista a esta vista, probablemente necesite usar las mismas esquinas redondeadas en ese UIVisualEffectView o no tendrá esquinas redondeadas.

Esquinas redondeadas con sombra para UIView: la captura de pantalla también usa un desenfoque que es un UIVisualEffectView normal que también tiene esquinas redondeadas

/// Inspiration: https://stackoverflow.com/a/25475536/129202
class ViewWithRoundedcornersAndShadow: UIView {
    private var theShadowLayer: CAShapeLayer?

    override func layoutSubviews() {
        super.layoutSubviews()

        if self.theShadowLayer == nil {
            let rounding = CGFloat.init(22.0)

            let shadowLayer = CAShapeLayer.init()
            self.theShadowLayer = shadowLayer
            shadowLayer.path = UIBezierPath.init(roundedRect: bounds, cornerRadius: rounding).cgPath
            shadowLayer.fillColor = UIColor.clear.cgColor

            shadowLayer.shadowPath = shadowLayer.path
            shadowLayer.shadowColor = UIColor.black.cgColor
            shadowLayer.shadowRadius = CGFloat.init(3.0)
            shadowLayer.shadowOpacity = Float.init(0.2)
            shadowLayer.shadowOffset = CGSize.init(width: 0.0, height: 4.0)

            self.layer.insertSublayer(shadowLayer, at: 0)
        }
    }
}
Jonny
fuente
4

Swift 5 y sin necesidad de "UIBezierPath"

    view.layer.cornerRadius = 15
    view.clipsToBounds = true
    view.layer.masksToBounds = false
    view.layer.shadowRadius = 7
    view.layer.shadowOpacity = 0.6
    view.layer.shadowOffset = CGSize(width: 0, height: 5)
    view.layer.shadowColor = UIColor.red.cgColor
Hari R Krishna
fuente
1
Nunca agrega ningún radio de esquina a la vista y la razón por la que lo necesita UIBezierPathes por razones de rendimiento en caso de que necesite reutilizar esa vista en particular.
Sharkes Monken
@SharkesMonken "NUNCA" realmente !!!! ? Vuelve a comprobarlo. Estoy usando este método en todo mi proyecto. Y si tiene alguna duda, consulte este video youtu.be/5qdF5ocDU7w
Hari R Krishna
No funciona; cornerRadius no tiene efecto
Amr Angry
por favor mira el video
Hari R Krishna
2

Para mejorar la respuesta de PiterPan y mostrar una sombra real (no solo un fondo sin desenfoque) con un botón circular en Swift 3:

override func viewDidLoad() {
    super.viewDidLoad()
    myButton.layer.masksToBounds = false
    myButton.layer.cornerRadius = myButton.frame.height/2
    myButton.clipsToBounds = true
}

override func viewDidLayoutSubviews() {
    addShadowForRoundedButton(view: self.view, button: myButton, opacity: 0.5)
}

func addShadowForRoundedButton(view: UIView, button: UIButton, opacity: Float = 1) {
    let shadowView = UIView()
    shadowView.backgroundColor = UIColor.black
    shadowView.layer.opacity = opacity
    shadowView.layer.shadowRadius = 5
    shadowView.layer.shadowOpacity = 0.35
    shadowView.layer.shadowOffset = CGSize(width: 0, height: 0)
    shadowView.layer.cornerRadius = button.bounds.size.width / 2
    shadowView.frame = CGRect(origin: CGPoint(x: button.frame.origin.x, y: button.frame.origin.y), size: CGSize(width: button.bounds.width, height: button.bounds.height))
    self.view.addSubview(shadowView)
    view.bringSubview(toFront: button)
}
endurecer
fuente
1

¡Aquí está la solución que funcionará!


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

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

Finalmente, para aplicar sombra con radio de esquina, llame como se indica a continuación:

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

Imagen de resultado

ingrese la descripción de la imagen aquí

ACTUALIZACIÓN : Si no ve el resultado esperado, intente llamar al método de extensión desde Main Thread , ¡eso funcionará con seguridad!

DispatchQueue.main.async {
    viewRounded.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)
}
Dhaval H. Nena
fuente
0

Si alguien necesita agregar sombras a los botones redondeados en Swift 3.0, este es un buen método para hacerlo.

func addShadowForRoundedButton(view: UIView, button: UIButton, shadowColor: UIColor, shadowOffset: CGSize, opacity: Float = 1) {
    let shadowView = UIView()
    shadowView.backgroundColor = shadowColor
    shadowView.layer.opacity = opacity
    shadowView.layer.cornerRadius = button.bounds.size.width / 2
    shadowView.frame = CGRect(origin: CGPoint(x: button.frame.origin.x + shadowOffset.width, y: button.frame.origin.y + shadowOffset.height), size: CGSize(width: button.bouds.width, height: button.bounds.height))
    self.view.addSubview(shadowView)
    view.bringSubview(toFront: button)
}

Utilice este método func viewDidLayoutSubviews()como se muestra a continuación:

override func viewDidLayoutSubviews() {
    addShadowForRoundedButton(view: self.view, button: button, shadowColor: .black, shadowOffset: CGSize(width: 2, height: 2), opacity: 0.5)
}

El efecto de este método es: ingrese la descripción de la imagen aquí

PiterPan
fuente
0

Extensión para sombra paralela y radio de esquina

extension UIView {

func dropShadow(color: UIColor, opacity: Float = 0.5, offSet: CGSize, shadowRadius: CGFloat = 1, scale: Bool = true, cornerRadius: CGFloat) {
    let shadowLayer = CAShapeLayer()
    shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath
    shadowLayer.fillColor = UIColor.white.cgColor
    shadowLayer.shadowColor = color.cgColor
    shadowLayer.shadowPath = shadowLayer.path
    shadowLayer.shadowOffset = offSet
    shadowLayer.shadowOpacity = opacity
    shadowLayer.shadowRadius = shadowRadius
    layer.insertSublayer(shadowLayer, at: 0)
}

}
Angi
fuente
0

Solución exacta para la sintaxis 2020

import UIKit
class ColorAndShadowButton: UIButton {
    override init(frame: CGRect) { super.init(frame: frame), common() }
    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder), common() }
    private func common() {
        // UIButton is tricky: you MUST set the clear bg in bringup;  NOT in layout
        backgroundColor = .clear
        clipsToBounds = false
        self.layer.insertSublayer(backgroundAndShadow, below: layer)
    }
    
   lazy var colorAndShadow: CAShapeLayer = {
        let s = CAShapeLayer()
        // set your button color HERE (NOT on storyboard)
        s.fillColor = UIColor.black.cgColor
        // now set your shadow color/values
        s.shadowColor = UIColor.red.cgColor
        s.shadowOffset = CGSize(width: 0, height: 10)
        s.shadowOpacity = 1
        s.shadowRadius = 10
        // now add the shadow
        layer.insertSublayer(s, at: 0)
        return s
    }()
    
    override func layoutSubviews() {
        super.layoutSubviews()
        // you MUST layout these two EVERY layout cycle:
        colorAndShadow = bounds
        colorAndShadow = UIBezierPath(roundedRect: bounds, cornerRadius: 12).cgPath
    }
}

ingrese la descripción de la imagen aquí

  • Tenga en cuenta que la respuesta principal muy antigua aquí es correcta pero tiene un error crítico

Tenga en cuenta que, UIButtonlamentablemente, es bastante diferente de UIViewiOS.

  • Debido a un comportamiento extraño en iOS, debe establecer el color de fondo (que por supuesto debe ser claro en este caso) en la inicialización, no en el diseño . Podrías dejarlo claro en el guión gráfico (pero normalmente haces clic en él para que tenga un color sólido simplemente para que puedas verlo cuando trabajes en el guión gráfico).

En general, los combos de sombras / redondeos son un verdadero problema en iOS. Soluciones similares:

https://stackoverflow.com/a/57465440/294884 - imagen + redondeado + sombras
https://stackoverflow.com/a/41553784/294884 - problema de dos esquinas
https://stackoverflow.com/a/59092828/294884 - Problema de "sombras + agujero" o "caja luminosa"
https://stackoverflow.com/a/57400842/294884 - el problema de "borde y espacio"
https://stackoverflow.com/a/57514286/294884 - "adición" básica beziers

Fattie
fuente
-1

Puedes crear un protocolo y ajustarlo a tu UIView, UIButton, Cell o lo que quieras así:

protocol RoundedShadowable: class {
    var shadowLayer: CAShapeLayer? { get set }
    var layer: CALayer { get }
    var bounds: CGRect { get }
}
​
extension RoundedShadowable {
    func applyShadowOnce(withCornerRadius cornerRadius: CGFloat, andFillColor fillColor: UIColor) {
        if self.shadowLayer == nil {
            let shadowLayer = CAShapeLayer()
            shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath
            shadowLayer.fillColor = fillColor.cgColor
            shadowLayer.shadowColor = UIColor.black.cgColor
            shadowLayer.shadowPath = shadowLayer.path
            shadowLayer.shadowOffset = CGSize(width: 0.0, height: 2.0)
            shadowLayer.shadowOpacity = 0.2
            shadowLayer.shadowRadius = 3
            self.layer.insertSublayer(shadowLayer, at: 0)
            self.shadowLayer = shadowLayer
        }
    }
}
​
class RoundShadowView: UIView, RoundedShadowable {

    var shadowLayer: CAShapeLayer?
    private let cornerRadius: CGFloat
    private let fillColor: UIColor

    init(cornerRadius: CGFloat, fillColor: UIColor) {
        self.cornerRadius = cornerRadius
        self.fillColor = fillColor
        super.init(frame: .zero)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.applyShadowOnce(withCornerRadius: self.cornerRadius, andFillColor: self.fillColor)
    }
}
​
class RoundShadowButton: UIButton, RoundedShadowable {

    var shadowLayer: CAShapeLayer?
    private let cornerRadius: CGFloat
    private let fillColor: UIColor

    init(cornerRadius: CGFloat, fillColor: UIColor) {
        self.cornerRadius = cornerRadius
        self.fillColor = fillColor
        super.init(frame: .zero)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.applyShadowOnce(withCornerRadius: self.cornerRadius, andFillColor: self.fillColor)
    }
}
Adam Smaka
fuente
-1

Usando CAShapeLayer y UIBezierPath podemos agregar fácilmente la sombra y el radio de esquina a UIView y la clase derivada de él como UIButton, UIImageView, UILabel, etc.

Agregaremos la extensión UIView y el buen punto de esto es que solo necesita escribir una línea de código para lograrlo.

También puede redondear una esquina específica.Simplemente agregue la siguiente extensión UIView en su proyecto:

 extension UIView {

  func addShadow(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: 
  CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {

    let shadowLayer = CAShapeLayer()
    let size = CGSize(width: cornerRadius, height: cornerRadius)
    let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
    shadowLayer.path = cgPath //2
    shadowLayer.fillColor = fillColor.cgColor //3
    shadowLayer.shadowColor = shadowColor.cgColor //4
    shadowLayer.shadowPath = cgPath
    shadowLayer.shadowOffset = offSet //5
    shadowLayer.shadowOpacity = opacity
    shadowLayer.shadowRadius = shadowRadius
    self.layer.addSublayer(shadowLayer)
  }
}

Ahora solo escriba el código debajo para agregar sombra y radio de esquina

  self.myView.addShadow(shadowColor: .black, offSet: CGSize(width: 2.6, height: 2.6), 
  opacity: 0.8, shadowRadius: 5.0, cornerRadius: 20.0, corners: [.topRight, .topLeft], 
  fillColor: .red)
Paresh Mangukiya
fuente
-1

Radio de esquina con sombra

Manera corta y sencilla !!!!!

extension CALayer {
    func applyCornerRadiusShadow(
        color: UIColor = .black,
        alpha: Float = 0.5,
        x: CGFloat = 0,
        y: CGFloat = 2,
        blur: CGFloat = 4,
        spread: CGFloat = 0,
        cornerRadiusValue: CGFloat = 0)
    {
        cornerRadius = cornerRadiusValue
        shadowColor = color.cgColor
        shadowOpacity = alpha
        shadowOffset = CGSize(width: x, height: y)
        shadowRadius = blur / 2.0
        if spread == 0 {
            shadowPath = nil
        } else {
            let dx = -spread
            let rect = bounds.insetBy(dx: dx, dy: dx)
            shadowPath = UIBezierPath(rect: rect).cgPath
        }
    }

Uso de código

btn.layer.applyCornerRadiusShadow(color: .black, 
                            alpha: 0.38, 
                            x: 0, y: 3, 
                            blur: 10, 
                            spread: 0, 
                            cornerRadiusValue: 24)

No es necesario maskToBound

Verifique que clipsToBounds sea falso.

SALIDA

ingrese la descripción de la imagen aquí

Pankaj Bhalala
fuente
Gracias por el código, pero no me funciona, ¿por qué? Consulte la imagen: imgur.com/dY5M3BL
Mc.Lover
@ Mc.Lover, ¿usaste maskToBound? o clipsToBounds?
Pankaj Bhalala