UIView mit abgerundeten Ecken und Schlagschatten?

390

Ich möchte eine benutzerdefinierte UIView...: Ich wollte nur eine leere weiße Ansicht mit abgerundeten Ecken und einem hellen Schlagschatten (ohne Lichteffekt). Ich kann durch ein jedes dieser ein tun , aber die üblichen clipToBounds/ maskToBoundsKonflikte auftreten.

Aditya Vaidyam
quelle
1
Da Sie in einem Kommentar unten sagen, dass dies mit CoreGraphics funktioniert, würde es Ihnen etwas ausmachen, die Antwort mit der Community zu teilen, damit Sie anderen in der gleichen Situation helfen können, in der sie versucht haben, Ihnen zu helfen?
lnafziger
Es tut mir leid, das ist schon lange her und ich habe keine Quelle mehr. Ich habe -drawRect überschrieben: und mit UIBezierPath ein Rechteck gezeichnet und einen Schatten auf die Ebene angewendet, die die Ansicht unterstützt ... wenn ich mich richtig erinnere. :)
Aditya Vaidyam
5
Die akzeptierte Antwort funktioniert nicht!
onmyway133
1
Mögliches Duplikat von Giving UIView abgerundeten Ecken
1
@Sachavijay Sie sollten die Daten beider Beiträge überprüfen, bevor Sie einen Kommentar abgeben.
Aditya Vaidyam

Antworten:

444

Der folgende Code - Schnipsel fügt eine Grenze, Grenzradius und Schlagschatten v, ein 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)];

Sie können die Einstellungen an Ihre Bedürfnisse anpassen.

Fügen Sie Ihrem Projekt außerdem das QuartzCore-Framework hinzu und:

#import <QuartzCore/QuartzCore.h>

Siehe meine andere Antwort bezüglich masksToBounds.


Hinweis

Dies funktioniert möglicherweise nicht in allen Fällen. Wenn Sie feststellen, dass diese Methode andere von Ihnen ausgeführte Zeichenvorgänge beeinträchtigt, lesen Sie bitte diese Antwort .

Evan Mulawski
quelle
83
Das Problem dabei ist, dass beim Festlegen des Eckenradius maskToBounds: YES festgelegt wird, während für den Schatten clipToBounds: NO erforderlich ist (wobei clipToBounds dasselbe tut wie maskToBounds)
Aditya Vaidyam
15
selbes Problem hier. Wenn ich eine Hintergrundfarbe habe, möchte ich, dass diese an den abgerundeten Ecken abgeschnitten wird. Dazu muss ich maskToBounds = TRUE verwenden, aber dann verschwindet der Schatten.
hfossli
3
Für Neulinge wie mich: Ich musste das QuartzCore-Framework in mein Projekt importieren, um Methoden für das Ebenenobjekt aufzurufen.
SilithCrowe
38
Um dies richtig zu machen, verwenden Sie eine innere Containeransicht, in der Ihr Rand und Ihre Hintergrundfarbe mit einem Eckenradius gespeichert sind. Diese Ansicht wird an Grenzen gebunden! Die zweite äußere Containeransicht beherbergt die erste, hat den gleichen Rahmen mit nur einem Schlagschatten. Ich habe dies einige Male getan, um einen Rand, einen Schlagschatten und einen Eckenradius zu kombinieren. Es ist wirklich nervig, aber es funktioniert wirklich gut.
Kpmurphy91
23
Funktioniert nicht Keine Ahnung, warum es so viele Stimmen gibt. War dies in älteren Versionen anwendbar?
Yarneo
627

Schnell

Geben Sie hier die Bildbeschreibung ein

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

Erkundung der Optionen

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Problem 1: Der Schatten wird abgeschnitten

Was ist, wenn es Unterschichten oder Unteransichten (wie ein Bild) gibt, deren Inhalt wir an die Grenzen unserer Ansicht kürzen möchten?

Geben Sie hier die Bildbeschreibung ein

Wir können dies mit erreichen

blueView.layer.masksToBounds = true

(Alternativ blueView.clipsToBounds = trueergibt sich das gleiche Ergebnis .)

Geben Sie hier die Bildbeschreibung ein

Aber oh nein! Der Schatten wurde auch abgeschnitten, weil er außerhalb der Grenzen liegt! Was ist zu tun? Was ist zu tun?

Lösung

Verwenden Sie separate Ansichten für den Schatten und den Rand. Die Basisansicht ist transparent und hat den Schatten. In der Rahmenansicht werden alle anderen Unterinhalte, die an den Rändern vorhanden sind, abgeschnitten.

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

Dies ergibt das folgende Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Problem 2: Schlechte Leistung

Das Hinzufügen abgerundeter Ecken und Schatten kann ein Leistungseinbruch sein. Sie können die Leistung verbessern, indem Sie einen vordefinierten Pfad für den Schatten verwenden und angeben, dass er gerastert werden soll. Der folgende Code kann dem obigen Beispiel hinzugefügt werden.

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

Weitere Informationen finden Sie in diesem Beitrag . Siehe hier und hier auch.

Diese Antwort wurde mit Swift 4 und Xcode 9 getestet.

Suragch
quelle
1
@ EICaptainv2.0, Wenn Sie nur einen Rand (und / oder einen Eckenradius) möchten, benötigen Sie keine separate Ansicht. Die separate Ansicht ist für die Situation vorgesehen, in der Sie runde Ecken und Schatten benötigen .
Suragch
2
Das funktioniert bei mir nicht. Wenn ich die Hintergrundfarbe so einstelle, dass sie in der Basisansicht gelöscht wird, erscheint kein Schatten mehr. Was mache ich falsch?
Rutger Huijsmans
3
Nicht funktioniert, Einstellung baseView.backgroundColor = UIColor.clearentfernt den Schatten. Nur wenn Sie eine Hintergrundfarbe festlegen, wird diese angezeigt.
Aleksander
2
NICHT FÜR MICH ARBEITEN.
Markus
4
Zu Ihrer Information Ich hatte anfangs das gleiche Problem wie andere Kommentatoren, bei denen der Schatten der baseView nicht angezeigt wurde, wenn die Hintergrundfarbe klar war. Das Problem war, dass ich nur den ersten Teil des Codes ausführte (das baseView-Zeug). Nachdem ich die borderView als Unteransicht hinzugefügt hatte, wurde der Schatten angezeigt. Es scheint, dass für die Anzeige des Schattens mindestens ein sichtbarer Rand (oder Hintergrund) in seiner Ansichtshierarchie vorhanden sein muss. Stellen Sie also sicher, dass borderView.layer.borderWidth> = 0 mit einer nicht transparenten borderView.layer.borderColor (oder einer nicht transparenten Hintergrundfarbe) ist
Mike Vosseller
79

Eine Möglichkeit, dies zu tun, besteht darin, die Ansicht mit abgerundeten Ecken in eine Ansicht mit dem Schlagschatten zu setzen.

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

Dann können Sie die shadowView hinzufügen, wo immer Sie möchten.

David C.
quelle
5
Amit, Sie müssen maskToBounds / clipToBounds = YES für die * roundView * festlegen. Stellen Sie dies NICHT auf shadowView ein. Ich habe den obigen Code nicht ausprobiert, weiß aber sicher, dass diese Lösung definitiv funktioniert, obwohl sie nicht ideal ist. Der höhere shadowRadius kümmert sich um die Eckenradiusbereiche. Setzen Sie den shadowRadius auf 0 oder 1 und Sie werden feststellen, was ich zu sagen versuche.
Deepak GM
2
So etwas wie shadowView.layer.shadowOpacity = 0.6; fehlt
Bo.
3
"shadowView.layer.opacity = 1.0" sollte "shadowView.layer.shadowOpacity = 1.0" sein
Chris
Funktioniert unter iOS 9, wenn shadowView.layer.shadowOpacity = 1.0 verwendet wird
Mansurov Ruslan
Code für shadowOpacity
Softlion
63

Schauen Sie sich das Beispielprojekt auf GitHub an, um sicherzustellen, dass Sie die Komponente korrekt verwenden.

Einfache Swift 5-Lösung ohne zusätzliche Unteransichten oder Unterklassen:

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

Beachten Sie, dass Sie Ihre Ansicht vor dem Aufruf mit dem Eckenradius und anderen Eigenschaften einrichten sollten addShadow.

Nennen Sie das danach einfach viewDidLoadso:

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

Endergebnis:

Ergebnis

Super einfach und unkompliziert!

Sergey Grischyov
quelle
Funktioniert das bei Schaltflächen? Weil es an meinem Ende nicht funktioniert.
Cesare
Ich habe versucht, genau die Schritte zu befolgen, die Sie vorgeschlagen haben. Aber immer noch kein Glück. Es wäre großartig, wenn Sie eine Probe (auf Github) teilen, um zu sehen, wie Sie es gemacht haben, was für mich und andere Menschen unmöglich erscheint.
Hemang
Es ist gelungen, es nur durch Entfernen dieser Zeile zum Laufen zu bringen layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath. Kann nicht erklären warum, hat jemand eine Erklärung dafür?
Rupin
@Curnelious Sie können sich die aktualisierte Antwort anhand eines Xcode-Projektbeispiels ansehen. Es kann nicht nicht funktionieren :)
Sergey Grischyov
3
Dies hat auch bei mir funktioniert. Eine Sache mehr ist, alle Unteransichten in Hintergrundfarbe zu löschen, damit nur die Containeransicht einen sichtbaren Hintergrund hat, und dies hat mein Problem gelöst. Vielen Dank!! @ SergeyGrischyov
Rishabh
42

Das hat bei mir funktioniert. Der Trick bestand darin, die Hintergrundfarbe von der Hauptansicht auf die Ebene zu verschieben.

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
quelle
Obwohl alle anderen Lösungen funktionieren und vielleicht allgemeiner sind, ist dies bei weitem die beste Lösung für das Problem. Das Hinzufügen von Unteransichten oder Unterschichten führt zu einer Welt oder zu Schmerzen beim Versuch, die Rahmengrößen beizubehalten, oder kann bestenfalls zu Leistungsproblemen führen.
Emem
Dies sollte die Antwort sein. Sauber und elegant.
Axy
Beste Lösung und auf jeden Fall elegant!
Roberto Ferraz
Wow, das funktioniert tatsächlich. Ich verstehe nicht, warum es funktionieren sollte - Sie würden denken, dass die Hintergrundfarbe der Ansicht unter iOS direkt der Eigenschaft layer.backgroundColor zugeordnet wird - aber es funktioniert. (Xcode 8, Swift 3.) Gut gemacht und danke. Dies sollte die akzeptierte Antwort sein.
Womble
Ich habe hier eine Swift 3.1-Version Ihrer Antwort erstellt UIView extension- stackoverflow.com/a/43295741/1313939 Vielen Dank für die Inspiration!
Sergey Grischyov
26

Ich habe das Problem mit dem folgenden Trick gelöst, als ich der Containeransicht einen Schattenpfad zugewiesen habe:

[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]

Beachten Sie, dass der Pfad zum Schatten ein abgerundetes Rechteck mit demselben Eckenradius wie der Hintergrund ist, den die Zelle enthält:

//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
quelle
Beste Antwort, weil es den richtigen Weg erklärt, einer runderen Ansicht in einer Ecke Schatten hinzuzufügen. Danke @Alex Stone
Programmierer
17

Wenn Sie wegen des gerundeten cornersvs. subviewsvs. kämpfen masksToBounds, versuchen Sie, meine Funktion zu verwenden:

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

Nennen Sie es aus Ihrer Sicht. Ob Ihre Ansicht abgerundete Ecken hat, unabhängig von ihrer Größe, ihrer Form - es wird ein schöner Schatten gezeichnet.

Behalten Sie einfach den Rückgabewert der Funktion bei, damit Sie darauf verweisen können, wenn Sie die Tabelle entfernen (oder beispielsweise verwenden insertSubview:aboveView:) möchten.

daniel.gindi
quelle
es funktioniert gut. Wenn die Ansicht jedoch über Gestenerkenner verfügt, funktioniert sie nicht. Wie können wir das lösen?
Manujmv
@manujmv Sehen Sie die Zeilen, in denen "// Dies bei Bedarf ändern" angegeben ist? Das ist was du brauchst. shadow.userInteractionEnabled = YES;
daniel.gindi
@manujmv dann sollten Sie die Frames der Ansicht und Unteransicht testen, um zu sehen, warum. da stimmt wohl etwas nicht. Dieser genaue Code funktioniert für mich in einigen sehr schönen Apps
daniel.gindi
2
Diese Lösung eignet sich hervorragend für UITableViews mit abgerundeten Ecken. Ich wünschte, ich könnte mehr Stimmen abgeben. Vielen Dank!
Chris Hart
@ CarlosEduardoLópez Sehen Sie die shadow.userInteractionEnabled = NO; // Modify this if neededLinie? Dies ist also bei Bedarf der Fall. userInteractionEnabledist eine einfache und beliebte Eigenschaft, mit der Sie bereits vertraut sein sollten :-)
daniel.gindi
12

Mit Swift 4 und Xcode 9 ist dies ein funktionierendes Beispiel für das Runden eines ImageViewSchlagschattens und eines Rahmens.

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

Geben Sie hier die Bildbeschreibung ein

Wenn Sie möchten, dass das Bild kreisförmig ist: (und ohne Rand angezeigt wird)

let cornerRadius = imageWidth / 2

Geben Sie hier die Bildbeschreibung ein

rbaldwin
quelle
7

Ich habe einen Helfer für UIView erstellt

@interface UIView (Helper)

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

Sie können es so nennen

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

Hier ist die Implementierung

- (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
quelle
2
Dies ist eine gute elegante Lösung. Stellen Sie vor der Verwendung sicher, dass Ihre Ansicht zu ihrer Übersicht hinzugefügt wurde. Ich habe einige Parameter hinzugefügt, um mehr Kontrolle über den Schatten zu erhalten, aber insgesamt funktioniert es perfekt. Vielen Dank!
Aaron Vegh
Dies ist eine gute Lösung, funktioniert aber nicht mit Autolayout: Die Ansicht wird am Ursprung 0,0
gderaco
5

Nach einem ganzen Tag Recherche der runden Eckansicht mit Schatten bin ich froh, meine benutzerdefinierte uiview-Klasse hier zu veröffentlichen, und hoffe, diese Frage zu beenden:

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

Sie müssen also KEINE Unteransicht in der Ansicht oder darunter in der Zielansicht hinzufügen. Fügen Sie einfach eine Ebene in der aktuellen Ansicht hinzu und führen Sie drei Schritte aus, um sie abzuschließen!

Schauen Sie sich die Kommentare im Code genau an, es ist hilfreich, die Komponente zu verstehen!

lwz7512
quelle
5

Etwas schnelles getestet in schnellem 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
        }
    }
}

Produziert

Geben Sie hier die Bildbeschreibung ein

Wenn Sie es im Inspektor wie folgt aktivieren:

Geben Sie hier die Bildbeschreibung ein

Das benutzerdefinierte Laufzeitattribut wird hinzugefügt, was zu Folgendem führt:

Geben Sie hier die Bildbeschreibung ein

(Ich habe vorher das hinzugefügt cornerRadius = 8)

:) :)

dGambit
quelle
5

Sie müssen verwenden shadowViewund verwendenroundView

Geben Sie hier die Bildbeschreibung ein

shadowView

  • Muss hat Hintergrundfarbe
  • Sollte zurückliegen roundView
  • Der Trick besteht darin, shadowViewein wenig nach innen zu legen , und der Schatten muss herausleuchten. Stellen Sie das insetsso ein, dass shadowViewes dahinter völlig unsichtbar istroundView

roundView

  • Unteransichten müssen abgeschnitten werden

Der Code

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

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

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

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

Oder Sie können einfach unten ohne Angabe tun clipToBounds/maskToBounds

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

Swift 3 & IBInspectable-Lösung: Inspiriert von Ades
Lösung

Erstellen Sie zunächst eine UIView-Erweiterung:

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

Wählen Sie dann einfach Ihre UIView im Interface Builder aus und stellen Sie Schatten EIN und Eckenradius wie folgt ein :

Auswahl Ihres UIView

Einstellen des Schattens EIN und des Eckenradius

Das Ergebnis!

Ergebnis

Thomás Calmon
quelle
Wie jede andere "Lösung" in diesem Thread funktioniert es einfach nicht, zumindest nicht unter iOS 11.0 / Swift 4.1.
Unentschlossenheit
Hast du "Swift 3" am Anfang des Threads gelesen? Das bedeutet, dass es sich um eine Swift 3-Lösung handelt. Ich habe sie in Swift 4.1 nicht getestet, weil ich sie nicht mehr benötige. Fühlen Sie sich frei, die Antwort zu bearbeiten und eine Lösung zu geben. ;) Prost
Thomás Calmon
3

Hier ist die Lösung für das Konfliktproblem masksToBounds, das bei mir funktioniert.

Nachdem Sie corderRadius / borderColor / shadow usw. festgelegt haben, setzen Sie masksToBounds auf NO:

v.layer.masksToBounds = NO;
Shaopeng Wang
quelle
Das hat bei mir funktioniert !! omg Ich habe fast alle Tricks gemacht, die du oben beantwortet hast! danke Shaopeng.
MontDeska
3

Schatten + Rand + Eckradius Geben Sie hier die Bildbeschreibung ein

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

Hier ist meine Version in Swift 3 für ein 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
quelle
3

Swift 4: Unterklasse von UIView erstellen

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
    }

}

Mit ..

Verwenden Sie die Klassenschattenansicht

benmore99
quelle
2

Wenn Sie Ihre Schreibfedern nicht ändern und die Hierarchie nicht wie vorgeschlagen anzeigen möchten, erledigt David C. diese Methode für Sie. Verwenden Sie diese Methode, um Ihrem UIImageView abgerundete Ecken und Schatten hinzuzufügen: Beispiel:

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

(!) Aus Leistungsgründen halte ich es nicht für eine gute Idee, diesen Code in so etwas wie UITableView zu verwenden, da dieser Code die Ansichtshierarchie ändert. Daher werde ich vorschlagen, Ihre Feder zu ändern und eine Containeransicht für den Schatteneffekt hinzuzufügen und Davic C.-Code zu verwenden.

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

Alter Thread noch aktuell ...

Ich habe Daniel Gindis Methode so bearbeitet, dass sie auch mit Schaltflächen usw. verwendet werden kann. Wenn jemand abgerundete Ecken benötigt oder runde Ecken und einen Rand kombinieren möchte, muss dies auf der Ebene der Ansicht festgelegt werden, die an diese Methode übergeben wird. Ich habe auch die Rasterung eingestellt, um sie etwas zu beschleunigen.

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

Das Folgende hat für mich am besten funktioniert (dieser Code befindet sich in der UIView-Erweiterung, daher bezeichnet self einige UIView, zu denen wir einen Schatten und eine runde Ecke hinzufügen müssen).

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

Der Hauptunterschied zwischen diesem und anderen Codebeispielen besteht darin, dass dadurch die Schattenansicht als Geschwisteransicht hinzugefügt wird (im Gegensatz zum Hinzufügen der aktuellen Ansicht als Unteransicht der Schattenansicht), wodurch die Notwendigkeit entfällt, die vorhandene Ansichtshierarchie in irgendeiner Weise zu ändern.

Mehul Parmar
quelle
1

Die Antwort von daniel.gindi oben hat den Trick für mich getan! (+1 daniel) Ich musste jedoch kleinere Anpassungen vornehmen - die Größe des shadowFrame so ändern, dass er der Frame-Größe der Ansicht entspricht, und die Benutzerinteraktion aktivieren. Hier ist der aktualisierte Code:

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

Ich möchte hinzufügen, dass ich in meinem Fall versucht habe, dies einem View-Controller eines Drittanbieters hinzuzufügen, dh ich hatte keine direkte Kontrolle über den Code. So habe ich die obige Funktion verwendet:

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

Ich nehme einige Änderungen am Code von daniel.gindi vor

Dies ist alles, was Sie brauchen, damit es funktioniert.

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

Sie müssen zwei verwenden UIViews, um dies zu erreichen. Einer UIViewarbeitet wie ein Schatten und der andere wie ein abgerundeter Rand.

Hier ist ein Code-Snippet a Class Methodmit Hilfe von 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;
}

Im obigen Code btnCompose_click:wird eine @requiredDelegatenmethode, die beim Klicken auf die Schaltfläche ausgelöst wird.

Und hier habe ich einen Button zu meinem hinzugefügt UIViewController:

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

Das Ergebnis sieht folgendermaßen aus:

Geben Sie hier die Bildbeschreibung ein

Vaibhav Saran
quelle
1

Ich habe so viele Lösungen aus diesem Beitrag ausprobiert und bin zu der folgenden Lösung gekommen. Dies ist eine vollständige Proof- Lösung, es sei denn, Sie müssen Schatten auf eine klare Farbansicht legen .

- (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
quelle
Der Ausdruck ist "narrensicher". :)
Ben Thomas
Ich habe nur das Englisch korrigiert. :) Die Lösung funktioniert.
Ben Thomas
1

Hier ist die Lösung, die sicher funktionieren wird!

Ich habe eine UIView-Erweiterung mit den erforderlichen Kanten erstellt, um Schatten wie unten beschrieben anzuwenden


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

Schließlich können Sie die Schattenfunktion für jede Ihrer UIView-Unterklassen wie folgt aufrufen. Sie können auch die Kante angeben, auf die Schatten angewendet werden sollen. Probieren Sie verschiedene Variationen aus, je nachdem, wie Sie die Parameter des folgenden Methodenaufrufs ändern müssen.

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

Ergebnisbild

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Dhaval H. Nena
quelle
0

Die Antwort von Evan Mulawski wird perfekt funktionieren. Der Haken ist, dass Sie die Hintergrundfarbe für die Ansicht auf clearColor und die Eigenschaft masksToBounds auf NO setzen müssen.

Sie können die gewünschte Farbe für die Ansicht festlegen

v.layer.backgroundColor = your color;

Hoffe das hilft..

Abdur Rahman
quelle
0

So machen Sie es, mit abgerundeten Ecken und abgerundeten Schatten, ohne sich um Pfade zu kümmern.

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

Die Ansicht mit Inhalt, in meinem Fall eine UIImageView, hat einen Eckenradius und muss daher bis zu den Grenzen maskiert werden.

Wir erstellen eine weitere gleich große Ansicht für die Schatten, setzen maskToBounds auf NO und fügen dann die Inhaltsansicht zur Containeransicht hinzu (z. B. shadowContainer).

Ford Davis
quelle
0

Ich schreibe diese UIView-Kategoriemethode, um dieses Problem zu lösen. Ich verwende separate Ansichten für den Schatten und den Eckenradius.

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

Swift 4- Lösung zum Runden von UICollectionViewCell und zum Hinzufügen von Schatten , ohne Erweiterungen und Komplikationen :)

Hinweis: Für einfache Ansichten zB Schaltflächen. Siehe die Antwort von @ suragch in diesem Beitrag. https://stackoverflow.com/a/34984063/7698092 . Erfolgreich auf Schaltflächen getestet

Im Fall , wenn jemand noch kämpfen runden die Ecken und fügen Schatten zugleich. Obwohl diese Lösung mit UICollectionViewCell funktioniert, kann sie auf jede Ansicht verallgemeinert werden.

Diese Technik funktionierte für mich ohne Erweiterungen und all die komplizierten Dinge. Ich arbeite mit storyBoard.

Technik

Sie müssen eine UIView (sagen wir "containerView") in Ihre UICollectionViewCell in storyBoard einfügen und alle erforderlichen Ansichten (Schaltflächen, Bilder usw.) in dieser containerView hinzufügen. Siehe den Screenshot. Struktur der Zelle

Schließen Sie die Steckdose für containerView an. Fügen Sie der CellforItemAtIndexPath-Delegatenfunktion die folgenden Codezeilen hinzu.

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

Ausgabe

Siehe den Simulator-Screenshot Abgerundete Ecken mit Schatten (UICollectionViewCell)

Awais Fayyaz
quelle
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
quelle
Hallo, danke für Ihre Antwort. Sie sollten Ihrem Code einige Kommentare hinzufügen, um ein wenig zu erklären, wie unter Antworten beschrieben .
Baptiste Mille-Mathias