Schnell - Probleme mit dem Eckenradius und dem Schlagschatten

85

Ich versuche eine Schaltfläche mit abgerundeten Ecken und einem Schlagschatten zu erstellen . Egal wie ich hochschalte, die Schaltfläche wird nicht richtig angezeigt. Ich habe es versucht masksToBounds = falseund masksToBounds = true, aber entweder funktioniert der Eckenradius und der Schatten nicht oder der Schatten funktioniert und der Eckenradius schneidet die Ecken der Schaltfläche nicht ab.

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
quelle
Sie möchten den Schatten und das Ausschneiden auf verschiedene Ebenen legen. Das Einrichten der Ebeneneigenschaften in drawRectist keine sehr gute Idee. Besser sie reinstecken initWithCoder.
David Berry
Nur für alle, die hier googeln, wie es oft bei sehr alten Fragen der Fall ist, hat die Top-Antwort hier, obwohl sie im Allgemeinen korrekt ist, jetzt einige kritische Fehler . (Ich habe eine korrigierte Antwort eingegeben.) Die meisten Leute, insbesondere ich, kopieren blind die oberste SO-Antwort und fügen sie ein - seien Sie vorsichtig, wenn es sich um eine sehr alte Qualitätssicherung handelt! (Es ist jetzt 2020 - jemand muss meine Antwort in 5 Jahren ersetzen!)
Fattie

Antworten:

143

Der folgende Swift 5 / iOS 12-Code zeigt, wie Sie eine Unterklasse festlegen UIButton, mit der Instanzen mit abgerundeten Ecken und Schatten erstellt werden können:

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

}

Je nach Bedarf können Sie ein UIButtonin Ihr Storyboard einfügen und dessen Klasse auf festlegen CustomButtonoder eine Instanz von CustomButtonprogrammgesteuert erstellen . Die folgende UIViewControllerImplementierung zeigt, wie eine CustomButtonInstanz programmgesteuert erstellt und verwendet wird :

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

}

Der vorherige Code erzeugt das folgende Bild im iPhone-Simulator:

Geben Sie hier die Bildbeschreibung ein

Imanou Petit
quelle
Mit iOS hatte ich Probleme mit meiner alten Implementierung, jetzt funktioniert es. Vielen Dank!
Carlodonz
1
Wie rufen Sie die Klasse von Ihrem Hauptansichts-Controller @POB aus auf?
Led
1
Gibt es eine Möglichkeit, die Schattenschicht zu trimmen und nur den sichtbaren Teil beizubehalten?
Johan Tingbacke
4
Da die Schattenschicht eine Unterschicht der eigenen Ebene der Schaltfläche ist, die masksToBounds = YESabgerundete Ecken aufweisen muss, wird der Schatten dann nicht auch abgeschnitten?
Mattsson
3
Das funktioniert fin, aber ich kann den Hintergrund der Schaltflächen nicht mehr ändern. Dies liegt wahrscheinlich an shadowLayer.fillColor. Was schlagen Sie vor? Vielen Dank !
GrayFox
34

Meine benutzerdefinierte Schaltfläche mit einigen Schatten und abgerundeten Ecken verwende ich direkt in der, Storyboardohne sie programmgesteuert berühren zu müssen .

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

Geben Sie hier die Bildbeschreibung ein

Umfang
quelle
Schnell und einfach.
Devbot10
1
Für mich war es der Trick, als ich den Code neu platzierte layoutSubviews().
Yash Bedi
14

Um Imanous Beitrag zu erweitern, können Sie die Schattenebene programmgesteuert zur benutzerdefinierten Schaltflächenklasse hinzufügen

@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
quelle
2
Sie maskieren den Schatten der Ebene und ich würde wirklich nicht empfehlen, die Schattenansicht auf die Übersicht der Schaltfläche zu setzen.
Mattsson
13

Ein alternativer Weg, um benutzerfreundlichere und konsistentere Schaltflächen zu erhalten.

Swift 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
quelle
1
Diese Methode ist am besten, da Sie eine andere Hintergrundfarbe für .normal und hervorgehoben haben können
Ryan Heitner
1
Nett. Ich habe viele verschiedene Methoden ausprobiert, um Hintergrundfarbe, Eckenradius und Schatten in meinen Schaltflächen zum Laufen zu bringen, aber dies war der einzige Weg, der funktioniert hat! Vielen Dank!
Harry Bloom
Dies ist die perfekte Lösung, danke dafür! Ein Hinweis: Wenn Sie UIButton programmgesteuert in UITableViewCell verwenden, muss dies in layoutSubviews () platziert werden.
bra.Scene
4

Dies wurde überarbeitet , um jede Ansicht zu unterstützen. Unterklassifizieren Sie Ihre Ansicht von dieser und es sollte abgerundete Ecken haben. Wenn Sie dieser Ansicht so etwas wie eine UIVisualEffectView als Unteransicht hinzufügen, müssen Sie wahrscheinlich dieselben abgerundeten Ecken für diese UIVisualEffectView verwenden, da sie sonst keine abgerundeten Ecken aufweist.

Abgerundete Ecken mit Schatten für UIView - Screenshot verwendet auch eine Unschärfe, die eine normale UIVisualEffectView ist, die auch abgerundete Ecken hat

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

Swift 5 & Keine Notwendigkeit von "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
quelle
1
Der Ansicht wird niemals ein Eckenradius hinzugefügt, und der Grund, warum Sie dies benötigen, UIBezierPathist aus Leistungsgründen, falls Sie diese bestimmte Ansicht wiederverwenden müssen.
Sharkes Monken
@SharkesMonken "NIE" wirklich !!!! ? Bitte überprüfen Sie noch einmal. Ich verwende diese Methode in meinem gesamten Projekt. Und wenn Sie irgendwelche Zweifel haben, überprüfen Sie bitte dieses Video youtu.be/5qdF5ocDU7w
Hari R Krishna
Funktioniert nicht; CornerRadius haben keine Wirkung
Amr Angry
Bitte überprüfen Sie das Video
Hari R Krishna
2

So verbessern Sie die Antwort von PiterPan und zeigen in Swift 3 einen echten Schatten (nicht nur einen Hintergrund ohne Unschärfe) mit einem kreisförmigen Knopf:

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)
}
Hardanger
quelle
1

Hier ist die Lösung, die funktionieren wird!


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
}

Um schließlich Schatten mit Eckradius anzuwenden, rufen Sie wie folgt auf:

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

Ergebnisbild

Geben Sie hier die Bildbeschreibung ein

UPDATE : Wenn Sie die erwartete Ausgabe nicht sehen, versuchen Sie, die Erweiterungsmethode vom Haupt-Thread aufzurufen. Das wird sicher funktionieren!

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

Wenn jemand in Swift 3.0 abgerundeten Schaltflächen Schatten hinzufügen muss , ist dies eine gute Methode.

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

Verwenden Sie diese Methode func viewDidLayoutSubviews()wie folgt:

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

Die Wirkung dieser Methode ist: Geben Sie hier die Bildbeschreibung ein

PiterPan
quelle
0

Erweiterung um Schlagschatten und Eckenradius

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
quelle
0

Genaue Lösung für die Syntax 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
    }
}

Geben Sie hier die Bildbeschreibung ein

  • Beachten Sie, dass die sehr alte Top-Antwort hier korrekt ist, aber einen kritischen Fehler aufweist

Beachten Sie, dass dies UIButtonleider ganz anders ist als UIViewin iOS.

  • Aufgrund eines seltsamen Verhaltens in iOS müssen Sie die Hintergrundfarbe (die in diesem Fall natürlich klar sein muss) bei der Initialisierung festlegen, nicht beim Layout . Sie können es einfach im Storyboard klarstellen (aber normalerweise klicken Sie darauf, um einfarbig zu sein, damit Sie es beim Arbeiten im Storyboard sehen können.)

Im Allgemeinen sind Kombinationen von Schatten / Rundungen unter iOS ein echtes Problem. Ähnliche Lösungen:

https://stackoverflow.com/a/57465440/294884 - Bild + gerundet + Schatten
https://stackoverflow.com/a/41553784/294884 - Zwei-Ecken-Problem
https://stackoverflow.com/a/59092828/294884 - "Shadows + Hole" - oder "Glowbox" -Problem
https://stackoverflow.com/a/57400842/294884 - Das "Border AND Gap" -Problem
https://stackoverflow.com/a/57514286/294884 - Grundlegendes "Hinzufügen" Bezier

Fattie
quelle
-1

Sie können ein Protokoll erstellen und es an Ihre UIView, UIButton, Cell oder was auch immer Sie möchten anpassen:

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

Mit CAShapeLayer und UIBezierPath können wir UIView und der daraus abgeleiteten Klasse wie UIButton, UIImageView, UILabel usw. problemlos Schatten- und Eckenradius hinzufügen.

Wir werden die UIView-Erweiterung hinzufügen. Der gute Punkt dabei ist, dass Sie nur eine Codezeile schreiben müssen, um dies zu erreichen.

Sie können auch eine bestimmte Ecke abrunden. Fügen Sie einfach die folgende UIView-Erweiterung in Ihr Projekt ein:

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

Schreiben Sie nun einfach den folgenden Code, um Schatten und Eckenradius hinzuzufügen

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

Eckradius mit Schatten

Kurzer und einfacher Weg !!!!!

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

Verwendung von Code

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

Keine Notwendigkeit maskToBound

Bitte überprüfen Sie, ob clipsToBounds falsch ist.

AUSGABE

Geben Sie hier die Bildbeschreibung ein

Pankaj Bhalala
quelle
Vielen Dank für den Code, funktioniert aber bei mir nicht. Warum? Bitte überprüfen Sie das Bild: imgur.com/dY5M3BL
Mc.Lover
@ Mc.Lover hast du maskToBound benutzt? oder clipsToBounds?
Pankaj Bhalala