358 Stimmen

Wie kann ich einen Schatten unter einer UIView zeichnen?

Ich versuche, einen Schatten unter den unteren Rand eines UIView in Cocoa Touch. Ich verstehe, dass ich Folgendes verwenden sollte CGContextSetShadow() um den Schatten zu zeichnen, aber die Quartz 2D-Programmieranleitung ist ein wenig vage:

  1. Speichern Sie den Grafikstatus.
  2. Rufen Sie die Funktion CGContextSetShadow und übergibt die entsprechenden Werte.
  3. Führen Sie alle Zeichnungen aus, auf die Sie Schatten anwenden möchten.
  4. Wiederherstellung des Grafikstatus

Ich habe das Folgende in einer UIView Unterklasse:

- (void)drawRect:(CGRect)rect {
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSaveGState(currentContext);
    CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
    CGContextRestoreGState(currentContext);
    [super drawRect: rect];
}

aber das funktioniert bei mir nicht, und ich weiß nicht, (a) wie ich weiter vorgehen soll und (b) ob ich irgendetwas an meinem UIView damit das funktioniert?

18voto

Axel Guilmin Punkte 10874

Einfache und saubere Lösung mit Interface Builder

Fügen Sie eine Datei mit dem Namen UIView.swift in Ihr Projekt ein (oder fügen Sie diese einfach in eine beliebige Datei ein):

import UIKit

@IBDesignable extension UIView {

    /* The color of the shadow. Defaults to opaque black. Colors created
    * from patterns are currently NOT supported. Animatable. */
    @IBInspectable var shadowColor: UIColor? {
        set {
            layer.shadowColor = newValue!.CGColor
        }
        get {
            if let color = layer.shadowColor {
                return UIColor(CGColor:color)
            }
            else {
                return nil
            }
        }
    }

    /* The opacity of the shadow. Defaults to 0. Specifying a value outside the
    * [0,1] range will give undefined results. Animatable. */
    @IBInspectable var shadowOpacity: Float {
        set {
            layer.shadowOpacity = newValue
        }
        get {
            return layer.shadowOpacity
        }
    }

    /* The shadow offset. Defaults to (0, -3). Animatable. */
    @IBInspectable var shadowOffset: CGPoint {
        set {
            layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
        }
        get {
            return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
        }
    }

    /* The blur radius used to create the shadow. Defaults to 3. Animatable. */
    @IBInspectable var shadowRadius: CGFloat {
        set {
            layer.shadowRadius = newValue
        }
        get {
            return layer.shadowRadius
        }
    }
}

Diese ist dann im Interface Builder für jede Ansicht im Utilities Panel > Attribute Inspector verfügbar:

Utilities Panel

Sie können den Schatten jetzt einfach einstellen.

Notas:
- Der Schatten erscheint nicht in IB, sondern nur zur Laufzeit.
- Wie Mazen Kasser sagte

Für diejenigen, die das nicht hinbekommen haben, [...] stellen Sie sicher, dass Clip Subviews ( clipsToBounds ) ist nicht aktiviert

13voto

Srikar Appalaraju Punkte 68866

Ich verwende dies als Teil meiner Hilfsmittel. Damit können wir nicht nur Schatten setzen, sondern auch eine abgerundete Ecke für jede UIView . Sie können auch einstellen, welche Farbe Sie bevorzugen. Normalerweise wird Schwarz bevorzugt, aber manchmal, wenn der Hintergrund nicht weiß ist, möchten Sie vielleicht etwas anderes. Hier ist, was ich benutze -

in utils.m
+ (void)roundedLayer:(CALayer *)viewLayer 
              radius:(float)r 
              shadow:(BOOL)s
{
    [viewLayer setMasksToBounds:YES];
    [viewLayer setCornerRadius:r];        
    [viewLayer setBorderColor:[RGB(180, 180, 180) CGColor]];
    [viewLayer setBorderWidth:1.0f];
    if(s)
    {
        [viewLayer setShadowColor:[RGB(0, 0, 0) CGColor]];
        [viewLayer setShadowOffset:CGSizeMake(0, 0)];
        [viewLayer setShadowOpacity:1];
        [viewLayer setShadowRadius:2.0];
    }
    return;
}

Um dies zu nutzen, müssen wir dies aufrufen - [utils roundedLayer:yourview.layer radius:5.0f shadow:YES];

7voto

neoneye Punkte 47046

Mauersegler 3

extension UIView {
    func installShadow() {
        layer.cornerRadius = 2
        layer.masksToBounds = false
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 1)
        layer.shadowOpacity = 0.45
        layer.shadowPath = UIBezierPath(rect: bounds).cgPath
        layer.shadowRadius = 1.0
    }
}

6voto

knig_T Punkte 1628

Wenn Sie StoryBoard verwenden möchten und nicht ständig Laufzeitattribute eintippen möchten, können Sie ganz einfach eine Erweiterung für Ansichten erstellen und diese in Storyboard nutzbar machen.

Schritt 1. Erweiterung erstellen

extension UIView {

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

@IBInspectable var shadowOpacity: Float {
    get {
        return layer.shadowOpacity
    }
    set {
        layer.shadowOpacity = newValue
    }
}

@IBInspectable var shadowOffset: CGSize {
    get {
        return layer.shadowOffset
    }
    set {
        layer.shadowOffset = newValue
    }
}

@IBInspectable var maskToBound: Bool {
    get {
        return layer.masksToBounds
    }
    set {
        layer.masksToBounds = newValue
    }
}
}

Schritt 2. Sie können diese Attribute nun im Storyboard verwenden storyboard image

4voto

O-mkar Punkte 4990

Sketch Shadow mit IBDesignable und IBInspectable in Swift 4

WIE BENUTZEN SIE ES

DEMO

SKIZZE UND XCODE NEBENEINANDER

Shadow Exampl

CODE

@IBDesignable class ShadowView: UIView {

    @IBInspectable var shadowColor: UIColor? {
        get {
            if let color = layer.shadowColor {
                return UIColor(cgColor: color)
            }
            return nil
        }
        set {
            if let color = newValue {
                layer.shadowColor = color.cgColor
            } else {
                layer.shadowColor = nil
            }
        }
    }

    @IBInspectable var shadowOpacity: Float {
        get {
            return layer.shadowOpacity
        }
        set {
            layer.shadowOpacity = newValue
        }
    }

    @IBInspectable var shadowOffset: CGPoint {
        get {
            return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
        }
        set {
            layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
        }

     }

    @IBInspectable var shadowBlur: CGFloat {
        get {
            return layer.shadowRadius
        }
        set {
            layer.shadowRadius = newValue / 2.0
        }
    }

    @IBInspectable var shadowSpread: CGFloat = 0 {
        didSet {
            if shadowSpread == 0 {
                layer.shadowPath = nil
            } else {
                let dx = -shadowSpread
                let rect = bounds.insetBy(dx: dx, dy: dx)
                layer.shadowPath = UIBezierPath(rect: rect).cgPath
            }
        }
    }
}

OUTPUT

DEMO OUTPUT

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X