wake-up-neo.com

UIView mit Schatten, abgerundeten Ecken und benutzerdefiniertem drawRect

Ich muss eine benutzerdefinierte UIView erstellen, die abgerundete Ecken, einen Rahmen, einen Schatten und die drawRect()-Methode überschreiben wird, um benutzerdefinierten Zeichnungscode bereitzustellen, mit dem mehrere gerade Linien in die Ansicht gezeichnet werden (ich muss hier einen schnellen, leichten Ansatz verwenden da viele dieser Ansichten gerendert werden können).

Das Problem, mit dem ich derzeit konfrontiert bin, ist, dass der Schatten nicht mehr für die runden Ecken gilt, sobald ich drawRect() in der Ansichtsklasse überschreibe (auch ohne benutzerdefinierten Code). Siehe das angehängte Bild für den Unterschied:

enter image description here

Im View Controller verwende ich den folgenden Code:

    view.layer.cornerRadius = 10;
    view.layer.masksToBounds = true;

    view.layer.borderColor = UIColor.grayColor().CGColor;
    view.layer.borderWidth = 0.5;

    view.layer.contentsScale = UIScreen.mainScreen().scale;
    view.layer.shadowColor = UIColor.blackColor().CGColor;
    view.layer.shadowOffset = CGSizeZero;
    view.layer.shadowRadius = 5.0;
    view.layer.shadowOpacity = 0.5;
    view.layer.masksToBounds = false;
    view.clipsToBounds = false;

In der überschriebenen drawContext() würde ich so etwas verwenden:

    var context:CGContext = UIGraphicsGetCurrentContext();
    CGContextSetStrokeColorWithColor(context, UIColor.redColor().CGColor);
    // Draw them with a 2.0 stroke width so they are a bit more visible.
    CGContextSetLineWidth(context, 2.0);
    CGContextMoveToPoint(context, 0.0, 0.0); //start at this point
    CGContextAddLineToPoint(context, 20.0, 20.0); //draw to this point
    CGContextStrokePath(context);

Wie bereits erwähnt, tritt das Schattenproblem auch ohne diesen hinzugefügten Code auf.

Gibt es eine andere/bessere Möglichkeit, leichte Elemente auf eine andere Ansicht zu zeichnen als auf diesen Ansatz, der mit runden Ecken und Schatten kompatibel ist? Ich möchte der Ansicht keine unnötigen zusätzlichen Ansichten oder Bildkontexte hinzufügen, da diese leicht und performant sein müssen.

47
BadmintonCat

Dies ist eine schwierige Frage. UIViews clipsToBounds ist notwendig, um die abgerundeten Ecken zu erhalten. Aber CALayers masksToBounds muss false sein, damit der Schatten sichtbar ist. Irgendwie funktioniert alles, wenn drawRect nicht überschrieben wird, aber eigentlich sollte es nicht.

Die Lösung besteht darin, eine Übersicht zu erstellen, um den Schatten bereitzustellen (in der Demonstration unten ist dies die Variable shadowView). Sie können Folgendes in Playground testen:

class MyView : UIView {
    override func drawRect(rect: CGRect) {
        let c = UIGraphicsGetCurrentContext()
        CGContextAddRect(c, CGRectMake(10, 10, 80, 80))
        CGContextSetStrokeColorWithColor(c , UIColor.redColor().CGColor)
        CGContextStrokePath(c)
    }
}

let superview = UIView(frame: CGRectMake(0, 0, 200, 200))

let shadowView = UIView(frame: CGRectMake(50, 50, 100, 100))
shadowView.layer.shadowColor = UIColor.blackColor().CGColor
shadowView.layer.shadowOffset = CGSizeZero
shadowView.layer.shadowOpacity = 0.5
shadowView.layer.shadowRadius = 5

let view = MyView(frame: shadowView.bounds)
view.backgroundColor = UIColor.whiteColor()
view.layer.cornerRadius = 10.0
view.layer.borderColor = UIColor.grayColor().CGColor
view.layer.borderWidth = 0.5
view.clipsToBounds = true

shadowView.addSubview(view)
superview.addSubview(shadowView)

Ergebnis: 

enter image description here

89
Mundi

Ich habe eine kleine Erweiterung für UIView geschrieben, um sowohl abgerundete Ecken als auch Schatten zu verwalten. Da die Variablen @IBInspectable sind, kann alles direkt im Storyboard gesetzt werden!

//
//  UIView extensions.Swift
//
//  Created by Frédéric ADDA on 25/07/2016.
//  Copyright © 2016 Frédéric ADDA. All rights reserved.
//

import UIKit

extension UIView {

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

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

            // Don't touch the masksToBound property if a shadow is needed in addition to the cornerRadius
            if shadow == false {
                self.layer.masksToBounds = true
            }
        }
    }


    func addShadow(shadowColor: CGColor = UIColor.black.cgColor,
               shadowOffset: CGSize = CGSize(width: 1.0, height: 2.0),
               shadowOpacity: Float = 0.4,
               shadowRadius: CGFloat = 3.0) {
        layer.shadowColor = shadowColor
        layer.shadowOffset = shadowOffset
        layer.shadowOpacity = shadowOpacity
        layer.shadowRadius = shadowRadius
    }
}

Und so sieht es im Storyboard aus:  storyboard

Das Ergebnis :  enter image description here

Es gibt eine Anforderung: NICHT berühren Sie entweder clipToBounds in der Ansicht (im Code oder in IB) oder maskenToBound in der Ebene.

NB: Ein Fall, in dem es nicht funktioniert: tableViews . Da UITableView automatisch clipToBounds unter der Motorhaube auslöst, können wir keinen Schlagschatten haben.

BEARBEITEN: Wie Claudia Fitero treffend bemerkt hat, müssen Sie in der Ansicht, zu der Sie einen Schatten hinzufügen, eine kleine Polsterung hinterlassen, ansonsten ist der Schatten nicht sichtbar. Grundsätzlich reicht eine 2px-Auffüllung (abhängig von Ihrem Schattenradius).

40
Frédéric Adda

Schatten wird von der Ebene der Innenansicht fallen gelassen. Wenn Sie das Beschneiden deaktivieren, wird das gesamte Ebenenrechteck mit dem Standardwert backgroundColor gefüllt, sodass der Schatten auch rechteckig wird. Anstatt die Maske mit einer abgerundeten Maske zu beschneiden, zeichnen Sie den Inhalt der Ebene einfach ab und zeichnen Sie sie selbst. Die Grenze von layer wird um ihre Grenzen gezogen, also müssen Sie sie auch selbst zeichnen.

Setzen Sie beispielsweise in backgroundColor die aktuelle Hintergrundfarbe auf clearColor und verwenden Sie die übergebene Farbe in drawRect, um ein abgerundetes Rechteck mit zu zeichnen.

Im folgenden Beispiel erkläre ich Eigenschaften als IBInspectable und die gesamte Klasse als IBDesignable, sodass alles im Storyboard festgelegt werden kann. Auf diese Weise können Sie sogar die standardmäßige Hintergrundauswahl verwenden, um Ihre abgerundete, gerade Farbe zu ändern.

Schnell

@IBDesignable class RoundRectView: UIView {

    @IBInspectable var cornerRadius: CGFloat = 0.0
    @IBInspectable var borderColor: UIColor = UIColor.blackColor()
    @IBInspectable var borderWidth: CGFloat = 0.5
    private var customBackgroundColor = UIColor.whiteColor()
    override var backgroundColor: UIColor?{
        didSet {
            customBackgroundColor = backgroundColor!
            super.backgroundColor = UIColor.clearColor()
        }
    }

    func setup() {
        layer.shadowColor = UIColor.blackColor().CGColor;
        layer.shadowOffset = CGSizeZero;
        layer.shadowRadius = 5.0;
        layer.shadowOpacity = 0.5;
        super.backgroundColor = UIColor.clearColor()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setup()
    }

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

    override func drawRect(rect: CGRect) {
        customBackgroundColor.setFill()
        UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius ?? 0).fill()

        let borderRect = CGRectInset(bounds, borderWidth/2, borderWidth/2)
        let borderPath = UIBezierPath(roundedRect: borderRect, cornerRadius: cornerRadius - borderWidth/2)
        borderColor.setStroke()
        borderPath.lineWidth = borderWidth
        borderPath.stroke()

        // whatever else you need drawn
    }
}

Swift 3

@IBDesignable class RoundedView: UIView {

@IBInspectable var cornerRadius: CGFloat = 0.0
@IBInspectable var borderColor: UIColor = UIColor.black
@IBInspectable var borderWidth: CGFloat = 0.5
private var customBackgroundColor = UIColor.white
override var backgroundColor: UIColor?{
    didSet {
        customBackgroundColor = backgroundColor!
        super.backgroundColor = UIColor.clear
    }
}

func setup() {
    layer.shadowColor = UIColor.black.cgColor
    layer.shadowOffset = CGSize.zero
    layer.shadowRadius = 5.0
    layer.shadowOpacity = 0.5
    super.backgroundColor = UIColor.clear
}

override init(frame: CGRect) {
    super.init(frame: frame)
    self.setup()
}

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

override func draw(_ rect: CGRect) {
    customBackgroundColor.setFill()
    UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius ?? 0).fill()

    let borderRect = bounds.insetBy(dx: borderWidth/2, dy: borderWidth/2)
    let borderPath = UIBezierPath(roundedRect: borderRect, cornerRadius: cornerRadius - borderWidth/2)
    borderColor.setStroke()
    borderPath.lineWidth = borderWidth
    borderPath.stroke()

    // whatever else you need drawn
}
}

Ziel-C .h

IB_DESIGNABLE
@interface RoundRectView : UIView
@property IBInspectable CGFloat cornerRadius;
@property IBInspectable UIColor *borderColor;
@property IBInspectable CGFloat borderWidth;
@end

Ziel-C .m

@interface RoundRectView()
@property UIColor *customBackgroundColor;
@end

@implementation RoundRectView

-(void)setup{
    self.layer.shadowColor = [UIColor blackColor].CGColor;
    self.layer.shadowOffset = CGSizeZero;
    self.layer.shadowRadius = 5.0;
    self.layer.shadowOpacity = 0.5;
    [super setBackgroundColor:[UIColor clearColor]];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self setup];
    }
    return self;
}

-(void)setBackgroundColor:(UIColor *)backgroundColor{
    self.customBackgroundColor = backgroundColor;
    super.backgroundColor = [UIColor clearColor];
}

-(void)drawRect:(CGRect)rect{
    [self.customBackgroundColor setFill];
    [[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.cornerRadius] fill];

    CGFloat borderInset = self.borderWidth/2;
    CGRect borderRect = CGRectInset(self.bounds, borderInset, borderInset);
    UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:borderRect cornerRadius:self.cornerRadius - borderInset];
    [self.borderColor setStroke];
    borderPath.lineWidth = self.borderWidth;
    [borderPath stroke];

    // whatever else you need drawn
}

@end

Ergebnis

18
Hodit

Hier ist die Swift3-Version von Hodit's answer, ich musste sie verwenden und hier finden und allgemeine Korrekturen für XCode 8 vornehmen. 

@IBDesignable class RoundRectView: UIView {

@IBInspectable var cornerRadius: CGFloat = 0.0
@IBInspectable var borderColor: UIColor = UIColor.black
@IBInspectable var borderWidth: CGFloat = 0.5
private var customBackgroundColor = UIColor.white
override var backgroundColor: UIColor?{
    didSet {
        customBackgroundColor = backgroundColor!
        super.backgroundColor = UIColor.clear
    }
}

func setup() {
    layer.shadowColor = UIColor.black.cgColor;
    layer.shadowOffset = CGSize.zero
    layer.shadowRadius = 5.0;
    layer.shadowOpacity = 0.5;
    super.backgroundColor = UIColor.clear
}

override init(frame: CGRect) {
    super.init(frame: frame)
    self.setup()
}

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

override func draw(_ rect: CGRect) {
    customBackgroundColor.setFill()
    UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius ?? 0).fill()

    let borderRect = bounds.insetBy(dx: borderWidth/2, dy: borderWidth/2)
    let borderPath = UIBezierPath(roundedRect: borderRect, cornerRadius: cornerRadius - borderWidth/2)
    borderColor.setStroke()
    borderPath.lineWidth = borderWidth
    borderPath.stroke()

    // whatever else you need drawn
}
}
8
amagain

Swift 3

Ich habe eine UIView-Erweiterung erstellt, deren im Grunde dieselbe Idee von Mundi vorgeschlagen wurde:

extension UIView {

func addShadowView() {
    //Remove previous shadow views
    superview?.viewWithTag(119900)?.removeFromSuperview()

    //Create new shadow view with frame
    let shadowView = UIView(frame: frame)
    shadowView.tag = 119900
    shadowView.layer.shadowColor = UIColor.black.cgColor
    shadowView.layer.shadowOffset = CGSize(width: 2, height: 3)
    shadowView.layer.masksToBounds = false

    shadowView.layer.shadowOpacity = 0.3
    shadowView.layer.shadowRadius = 3
    shadowView.layer.shadowPath = UIBezierPath(rect: bounds).cgPath
    shadowView.layer.rasterizationScale = UIScreen.main.scale
    shadowView.layer.shouldRasterize = true

    superview?.insertSubview(shadowView, belowSubview: self)
}}

Benutzen:

class MyCVCell: UICollectionViewCell {

@IBOutlet weak var containerView: UIView!

override func awakeFromNib() {
    super.awakeFromNib()
}

override func draw(_ rect: CGRect) {
    super.draw(rect)
    containerView.addShadowView()
}}

 Result

4
xlsmearlx

Swift 3 Lösung

Angepasst an Mundis Antwort 

class MyView : UIView {
        override func draw(_ rect: CGRect) {
            let c = UIGraphicsGetCurrentContext()
            c!.addRect(CGRect(x: 10, y: 10, width: 80, height: 80))
            c!.setStrokeColor(UIColor.red.cgColor)
            c!.strokePath()
        }
    }

let superview = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))

let shadowView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
shadowView.layer.shadowColor = UIColor.black.cgColor
shadowView.layer.shadowOffset = CGSize.zero
shadowView.layer.shadowOpacity = 0.5
shadowView.layer.shadowRadius = 5

let view = MyView(frame: shadowView.bounds)
view.backgroundColor = UIColor.white
view.layer.cornerRadius = 10.0
view.layer.borderColor = UIColor.gray.cgColor
view.layer.borderWidth = 0.5
view.clipsToBounds = true

shadowView.addSubview(view)
superview.addSubview(shadowView)
3
Oscar

Ich finde den folgenden Link hilfreich, um das Einstellen des Dropshadow zu verstehen:

So fügen Sie einem UIView einen Schatten hinzu

Um die runde Ecke für UIVIEW festzulegen, setzen Sie einfach den layer.cornerRadius-Wert im Interface Builder. Bitte überprüfen Sie den Screenshot .  enter image description here

3
Zulqarnain

Die Lösung scheint viel einfacher zu sein, als das Problem vermuten lässt. Ich hatte dies mit einer meiner Ansichten und nutzte den Kern der Antwort von @ Hodit, um sie zum Laufen zu bringen. Das ist alles was Sie eigentlich brauchen:

- (void) drawRect:(CGRect)rect {
    // make sure the background is set to a transparent color using IB or code
    // e.g.: self.backgroundColor = [UIColor clearColor]; 

    // draw a rounded rect in the view
    [[UIColor whiteColor] setFill];
    [[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:5.0] fill];

    // apply shadow if you haven't already
    self.layer.masksToBounds = NO;
    self.layer.shadowColor = [[UIColor blackColor] CGColor];
    self.layer.shadowOffset = CGSizeMake(0.0,3.0);
    self.layer.shadowRadius= 1.0;
    self.layer.shadowOpacity = 0.1;

    // more code here

}

Beachten Sie, dass Subviews dadurch nicht geschnitten werden. Alles, was in der Ansicht auf 0,0 eingestellt ist, überlappt die sichtbare obere obere Ecke.

1
ar34z

Das ist meine Lösung. Wenn Sie über mehrere Ansichtstypen wie UIView, UIControl, UITableView usw. verfügen und keine Unterklasse erstellen möchten, oder Sie möchten diesen Effekt mit den geringsten Änderungen in Ihren Code einfügen, könnten Sie dies vielleicht auch tun sind auf der Suche nach.

Ziel-C.h

#import <UIKit/UIKit.h>

@interface UIView (CornerAndShadow)

- (void)setCornerAndShadow;

@end

Ziel-C.m

#import "UIView+CornerAndShadow.h"
#import <Masonry.h>

@implementation UIView (CornerAndShadow)

- (void)setCornerAndShadow {
    // constants
    CGFloat fCornerRadius = 9.f;

    // only work for views with superview
    if (self.superview == nil) {
        return;
    }

    // set corner
    self.layer.cornerRadius = fCornerRadius;
    self.layer.masksToBounds = YES;

    // create and configure shadowView
    UIView *shadowView = [UIView new];
    shadowView.backgroundColor = self.backgroundColor; // just to make shadow visible
    shadowView.layer.cornerRadius = fCornerRadius;
    shadowView.layer.shadowColor = [UIColor redColor].CGColor;
    shadowView.layer.shadowOffset = CGSizeMake(0, 3.f);
    shadowView.layer.shadowOpacity = 0.5f;
    shadowView.layer.shadowRadius = 5.f;

    // put shadowView into superview right below self
    [self.superview insertSubview:shadowView belowSubview:self];

    // set shadowView's frame equal to self
    [shadowView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self);
    }];
    // use this if you're not using autolayout, and can get real frame here
    // shadowView.frame = self.frame;
}

@end
1
arthurdai

Vergessen Sie nicht, zusätzlich zur Lösung von Frederic Adda die Ansicht, die Schatten enthält, mit einer Auffüllung zum Superview zu positionieren, wo der Schatten gezeichnet werden kann. Andernfalls wird der Schatten abgeschnitten ... Ich habe diesen Fehler in meiner benutzerdefinierten Zelle gemacht und dachte, die Lösung sei falsch, bis ich rundherum einen Abstand von 8 Pixeln hinzugefügt habe.

1
Claudia Fitero

In Swift. Was für mich funktionierte, war das Hinzufügen von:

    self.noteImage.layer.masksToBounds = false

Der vollständige Code lautet also:

    self.noteImage.layer.masksToBounds = false
    self.noteImage.layer.shadowColor = UIColor.redColor().CGColor
    self.noteImage.layer.shadowOpacity = 0.5
    self.noteImage.layer.shadowOffset = CGSize(width: 2, height: 2)
    self.noteImage.layer.shadowRadius = 1

    self.noteImage.layer.shadowPath = UIBezierPath(rect: noteImage.bounds).CGPath
    self.noteImage.layer.shouldRasterize = true
1
Maria Ortega

Probieren Sie es aus, es ist Arbeit für mich ...

    yourView.layer.shadowColor = UIColor.blackColor().CGColor
    yourView.layer.shadowOpacity = 0.5
    yourView.layer.shadowOffset = CGSize(width: 3, height: 3)
    yourView.layer.shadowRadius = 05

    yourView.layer.shadowPath = UIBezierPath(rect: yourView.bounds).CGPath
    yourView.layer.shouldRasterize = true
1
Piyush Sanepara

In Swift 4.1. Um abgerundete Ecken von UIView zu erstellen, habe ich die Erweiterung von UIView wie folgt erstellt.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var viewOuter: UIView!
    @IBOutlet weak var viewInner: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        viewOuter.backgroundColor = UIColor.clear
        viewInner.roundCorners(15.0)
        viewOuter.addViewShadow()
    }
}
extension UIView {
    public func roundCorners(_ cornerRadius: CGFloat) {
        self.layer.cornerRadius = cornerRadius
        self.clipsToBounds = true
        self.layer.masksToBounds = true
    }

    public func addViewShadow() {
        DispatchQueue.main.asyncAfter(deadline: (.now() + 0.2)) {
            let shadowLayer = CAShapeLayer()
            shadowLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: 15).cgPath
            shadowLayer.fillColor = UIColor.white.cgColor

            shadowLayer.shadowColor = UIColor.lightGray.cgColor
            shadowLayer.shadowPath = shadowLayer.path
            shadowLayer.shadowOffset = CGSize(width: 2.6, height: 2.6)
            shadowLayer.shadowOpacity = 0.8
            shadowLayer.shadowRadius = 8.0
            self.layer.insertSublayer(shadowLayer, at: 0)
        }
    }
}

 enter image description here  enter image description here

0
GSK

Ich benutze diese Erweiterung um UIView:

Import UIKit

extension UIView {

    /// A property that accesses the backing layer's opacity.
    @IBInspectable
    open var opacity: Float {
        get {
            return layer.opacity
        }
        set(value) {
            layer.opacity = value
        }
    }

    /// A property that accesses the backing layer's shadow
    @IBInspectable
    open var shadowColor: UIColor? {
        get {
            guard let v = layer.shadowColor else {
                return nil
            }

            return UIColor(cgColor: v)
        }
        set(value) {
            layer.shadowColor = value?.cgColor
        }
    }

    /// A property that accesses the backing layer's shadowOffset.
    @IBInspectable
    open var shadowOffset: CGSize {
        get {
            return layer.shadowOffset
        }
        set(value) {
            layer.shadowOffset = value
        }
    }

    /// A property that accesses the backing layer's shadowOpacity.
    @IBInspectable
    open var shadowOpacity: Float {
        get {
            return layer.shadowOpacity
        }
        set(value) {
            layer.shadowOpacity = value
        }
    }

    /// A property that accesses the backing layer's shadowRadius.
    @IBInspectable
    open var shadowRadius: CGFloat {
        get {
            return layer.shadowRadius
        }
        set(value) {
            layer.shadowRadius = value
        }
    }

    /// A property that accesses the backing layer's shadowPath.
    @IBInspectable
    open var shadowPath: CGPath? {
        get {
            return layer.shadowPath
        }
        set(value) {
            layer.shadowPath = value
        }
    }


    /// A property that accesses the layer.cornerRadius.
    @IBInspectable
    open var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set(value) {
            layer.cornerRadius = value
        }
    }


    /// A property that accesses the layer.borderWith.
    @IBInspectable
    open var borderWidth: CGFloat {
        get {
            return layer.borderWidth
        }
        set(value) {
            layer.borderWidth = value
        }
    }

    /// A property that accesses the layer.borderColor property.
    @IBInspectable
    open var borderColor: UIColor? {
        get {
            guard let v = layer.borderColor else {
                return nil
            }
            return UIColor(cgColor: v)
        }
        set(value) {
            layer.borderColor = value?.cgColor
        }
    }
}
0
MBH

Dies ist eine ältere Frage, aber ich hätte einfach alles in Ihrer benutzerdefinierten Zeichenmethode wie unten beschrieben gemacht.

Normalerweise mache ich das, wenn ich weiß, dass ich meiner abgerundeten Ansicht einen Schlagschatten hinzufügen möchte (was natürlich bedeutet, dass ich masksToBounds nicht verwenden möchte).

Sie müssen der Hierarchie auch keine zusätzliche "Schattenansicht" hinzufügen.

@IBDesignable
class RoundedView: UIView {

@IBInspectable
var cornerRadius: CGFloat = 0

override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext() else { return }
    // You could use custom IBInspectable attributes
    // for the stroke and fill color.
    context.setFillColor(UIColor.white.cgColor)
    context.setStrokeColor(UIColor.orange.cgColor)
    // Add a clipping path to get the rounded look
    // you want.
    UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).addClip()
    // Fill and stroke your background.
    let background = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
    background.lineWidth = 2
    background.fill()
    background.stroke()
}

private func shadow() {
    layer.shadowColor = UIColor.black.cgColor
    layer.shadowRadius = 5
    layer.shadowOpacity = 0.5
    layer.shadowOffset = CGSize.zero
}

override func awakeFromNib() {
    super.awakeFromNib()
    shadow()
}
}
0
WBuck