2016-06-07 8 views
11

Ich schaute auf, aber ich konnte nicht finden, wie ich UIView einen inneren Schatten hinzufügen kann, nur oben (von oben nach unten) für Swift. Was ist der beste Weg, den inneren Kreis in Swift hinzuzufügen?Hinzufügen eines inneren Schattens zum Anfang von UIView

Edit: Ich habe ein paar Fragen & Antworten auf SO gefunden, aber sie sind entweder in obj-c oder sieht so kompliziert aus. Ich habe nur für eine Swifty Art und Weise, wenn es irgendwelche gibt

Was ich erreichen möchte:

enter image description here

+2

dauerte 2 Sekunden: https://github.com/inamiy/YIInnerShadowView – Arbitur

+0

@gotnull Ich habe diese Frage gefunden, aber ich konnte nicht herausfinden, wie man es nur oben hinzufügen. Auch Arbitur, dein Link ist in objective-c, den ich nicht übersetzen konnte. In seiner SO-Antwort sieht es ziemlich kompliziertes Stück Code und all seine Seiten aus. Es benutzt auch nicht so einfach wie 'CGSizeMake', deshalb wollte ich danach fragen. Ich war nur auf der Suche nach einem Swifty Weg – senty

+1

Wenn Sie sicherstellen möchten, dass der Schatten nur entlang des oberen Randes bleibt, unabhängig vom Weichzeichnerradius/Offset/etc.und blutet nicht in die anderen Grenzen. Am besten ist es, wenn Sie eine "UIImageView" als untergeordnete Ansicht hinzufügen, die an der oberen Grenze befestigt ist und sich über die gesamte Breite erstreckt. Wenn Sie eine spezielle Behandlung an den Seitenrändern benötigen (wie Ihr Screenshot zu suggerieren scheint), wird vielleicht ein dehnbares Bild mit Einsätzen den Zweck erfüllen. –

Antwort

-2

Verwenden folgende Bibliothek:

https://github.com/nlampi/UIView-InnerShadow

// Add a shadow to the top of the view only 
[exampleView addInnerShadowWithRadius:3.0f 
          andColor:[UIColor colorWithWhite:0 alpha:0.45f] 
          inDirection:NLInnerShadowDirectionTop]; 

Ich habe mein Bestes getan, um die Bibliothekserweiterung in Swift umzuwandeln (dies ist nicht getestet, daher kann ich nicht garantieren, dass es funktioniert). Es sollte dich aber auf die richtige Spur bringen.

import UIKit 

extension UIView { 

    struct NLInnerShadowDirection: OptionSetType { 
     let rawValue: Int 

     static let None = NLInnerShadowDirection(rawValue: 0) 
     static let Left = NLInnerShadowDirection(rawValue: 1 << 0) 
     static let Right = NLInnerShadowDirection(rawValue: 1 << 1) 
     static let Top = NLInnerShadowDirection(rawValue: 1 << 2) 
     static let Bottom = NLInnerShadowDirection(rawValue: 1 << 3) 
     static let All = NLInnerShadowDirection(rawValue: 15) 
    } 

    func removeInnerShadow() { 
     for view in self.subviews { 
      if (view.tag == 2639) { 
       view.removeFromSuperview() 
       break 
      } 
     } 
    } 

    func addInnerShadow() { 
     let c = UIColor() 
     let color = c.colorWithAlphaComponent(0.5) 

     self.addInnerShadowWithRadius(3.0, color: color, inDirection: NLInnerShadowDirection.All) 
    } 

    func addInnerShadowWithRadius(radius: CGFloat, andAlpha: CGFloat) { 
     let c = UIColor() 
     let color = c.colorWithAlphaComponent(alpha) 

     self.addInnerShadowWithRadius(radius, color: color, inDirection: NLInnerShadowDirection.All) 
    } 

    func addInnerShadowWithRadius(radius: CGFloat, andColor: UIColor) { 
     self.addInnerShadowWithRadius(radius, color: andColor, inDirection: NLInnerShadowDirection.All) 
    } 

    func addInnerShadowWithRadius(radius: CGFloat, color: UIColor, inDirection: NLInnerShadowDirection) { 
     self.removeInnerShadow() 

     let shadowView = self.createShadowViewWithRadius(radius, andColor: color, direction: inDirection) 

     self.addSubview(shadowView) 
    } 

    func createShadowViewWithRadius(radius: CGFloat, andColor: UIColor, direction: NLInnerShadowDirection) -> UIView { 
     let shadowView = UIView(frame: CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)) 
     shadowView.backgroundColor = UIColor.clearColor() 
     shadowView.tag = 2639 

     let colorsArray: Array = [ andColor.CGColor, UIColor.clearColor().CGColor ] 

     if direction.contains(.Top) { 
      let xOffset: CGFloat = 0.0 
      let topWidth = self.bounds.size.width 

      let shadow = CAGradientLayer() 
      shadow.colors = colorsArray 
      shadow.startPoint = CGPointMake(0.5, 0.0) 
      shadow.endPoint = CGPointMake(0.5, 1.0) 
      shadow.frame = CGRectMake(xOffset, 0, topWidth, radius) 
      shadowView.layer.insertSublayer(shadow, atIndex: 0) 
     } 

     if direction.contains(.Bottom) { 
      let xOffset: CGFloat = 0.0 
      let bottomWidth = self.bounds.size.width 

      let shadow = CAGradientLayer() 
      shadow.colors = colorsArray 
      shadow.startPoint = CGPointMake(0.5, 1.0) 
      shadow.endPoint = CGPointMake(0.5, 0.0) 
      shadow.frame = CGRectMake(xOffset, self.bounds.size.height - radius, bottomWidth, radius) 
      shadowView.layer.insertSublayer(shadow, atIndex: 0) 
     } 

     if direction.contains(.Left) { 
      let yOffset: CGFloat = 0.0 
      let leftHeight = self.bounds.size.height 

      let shadow = CAGradientLayer() 
      shadow.colors = colorsArray 
      shadow.frame = CGRectMake(0, yOffset, radius, leftHeight) 
      shadow.startPoint = CGPointMake(0.0, 0.5) 
      shadow.endPoint = CGPointMake(1.0, 0.5) 
      shadowView.layer.insertSublayer(shadow, atIndex: 0) 
     } 

     if direction.contains(.Right) { 
      let yOffset: CGFloat = 0.0 
      let rightHeight = self.bounds.size.height 

      let shadow = CAGradientLayer() 
      shadow.colors = colorsArray 
      shadow.frame = CGRectMake(self.bounds.size.width - radius, yOffset, radius, rightHeight) 
      shadow.startPoint = CGPointMake(1.0, 0.5) 
      shadow.endPoint = CGPointMake(0.0, 0.5) 
      shadowView.layer.insertSublayer(shadow, atIndex: 0) 
     } 

     return shadowView 
    } 
} 
+0

Danke für die Beantwortung. Muss ich dafür einen Überbrückungskopf erstellen? Gibt es einen Weg, Swift zu erreichen? Ich wäre dankbar – senty

+0

@senty: Ja, der einfachste Weg wäre, einen Bridging-Header zu erstellen, da es eine Menge Code in Objective-C gibt. – fuzz

+0

Ich zögere mit Bridging-Header, weil jedes Mal, wenn ich es versuche, bricht es weiter. Wenn du Zeit hast, kannst du mir bitte sagen, welche Teile nötig sind, damit ich es in Swift reinhabe? Es wäre sehr hilfreich für alle – senty

9

Ich benutze internen Schatten zu UIView mit Objective-C. Ich versuche Code schnell zu übersetzen. Bitte vergib mir meine arme schnelle Syntax

Sie die Funktion unten in UIView.didMoveToSuperview

func drawShadow() { 
    if nil == self.shadowLayer { 
     let size = self.frame.size 
     self.clipsToBounds = true 
     let layer: CALayer = CALayer() 
     layer.backgroundColor = UIColor.lightGrayColor().CGColor 
     layer.position = CGPointMake(size.width/2, -size.height/2 + 0.5) 
     layer.bounds = CGRectMake(0, 0, size.width, size.height) 
     layer.shadowColor = UIColor.darkGrayColor().CGColor 
     layer.shadowOffset = CGSizeMake(0.5, 0.5) 
     layer.shadowOpacity = 0.8 
     layer.shadowRadius = 5.0 
     self.shadowLayer = layer 

     self.layer.addSublayer(layer) 
    } 
} 
+1

Mit Abstand die beste Antwort. MEINER BESCHEIDENEN MEINUNG NACH. Bei anderen Antworten werden Farbverläufe verwendet, die in Core Graphics nicht dargestellt werden. – beyowulf

+0

@beyowulf danke für die Korrektur meines Codes. –

+0

Woher kommt 'self.shadowLayer'? –

16

Hier ist eine reine Swift-Version, die ich aufgepeitscht anrufen:

public class EdgeShadowLayer: CAGradientLayer { 

    public enum Edge { 
     case Top 
     case Left 
     case Bottom 
     case Right 
    } 

    public init(forView view: UIView, 
       edge: Edge = Edge.Top, 
       shadowRadius radius: CGFloat = 20.0, 
       toColor: UIColor = UIColor.white, 
       fromColor: UIColor = UIColor.black) { 
     super.init() 
     self.colors = [fromColor.cgColor, toColor.cgColor] 
     self.shadowRadius = radius 

     let viewFrame = view.frame 

     switch edge { 
      case .Top: 
       startPoint = CGPoint(x: 0.5, y: 0.0) 
       endPoint = CGPoint(x: 0.5, y: 1.0) 
       self.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: shadowRadius) 
      case .Bottom: 
       startPoint = CGPoint(x: 0.5, y: 1.0) 
       endPoint = CGPoint(x: 0.5, y: 0.0) 
       self.frame = CGRect(x: 0.0, y: viewFrame.height - shadowRadius, width: viewFrame.width, height: shadowRadius) 
      case .Left: 
       startPoint = CGPoint(x: 0.0, y: 0.5) 
       endPoint = CGPoint(x: 1.0, y: 0.5) 
       self.frame = CGRect(x: 0.0, y: 0.0, width: shadowRadius, height: viewFrame.height) 
      case .Right: 
       startPoint = CGPoint(x: 1.0, y: 0.5) 
       endPoint = CGPoint(x: 0.0, y: 0.5) 
       self.frame = CGRect(x: viewFrame.width - shadowRadius, y: 0.0, width: shadowRadius, height: viewFrame.height) 
     } 
    } 

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

es zu benutzen,

let topShadow = EdgeShadowLayer(forView: targetView, edge: .Top) 
view.layer.addSublayer(topShadow) 

Beachten Sie, dass standardmäßig ein Schwarz-zu-Weiß-Farbverlauf mit einer Tiefe von 20 Pixel eingestellt wird.

Der vollständige Code mit einem Beispiel UIViewController, mit dem Sie Schatten in allen vier Ecken einer Ansicht umschalten können, finden Sie unter https://github.com/jrtibbetts/Tenebrae. Ich habe auch die EdgeShadowLayer ziemlich gründlich dokumentiert.

3

Ich schrieb @NRitH Lösung auf Swift 3, auch etwas Refactoring:

final class SideShadowLayer: CAGradientLayer { 
    enum Side { 
     case top, 
     bottom, 
     left, 
     right 
    } 

    init(frame: CGRect, side: Side, shadowWidth: CGFloat, 
     fromColor: UIColor = .black, 
     toColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0), 
     opacity: Float = 0.5) { 
     super.init() 

     colors = [fromColor.cgColor, toColor.cgColor] 
     self.opacity = opacity 

     switch side { 
     case .bottom: 
      startPoint = CGPoint(x: 0.5, y: 1.0) 
      endPoint = CGPoint(x: 0.5, y: 0.0) 
      self.frame = CGRect(x: 0, y: frame.height - shadowWidth, width: frame.width, height: shadowWidth) 

     case .top: 
      startPoint = CGPoint(x: 0.5, y: 0.0) 
      endPoint = CGPoint(x: 0.5, y: 1.0) 
      self.frame = CGRect(x: 0, y: 0, width: frame.width, height: shadowWidth) 

     case .left: 
      startPoint = CGPoint(x: 0.0, y: 0.5) 
      endPoint = CGPoint(x: 1.0, y: 0.5) 
      self.frame = CGRect(x: 0, y: 0, width: shadowWidth, height: frame.height) 

     case .right: 
      startPoint = CGPoint(x: 1.0, y: 0.5) 
      endPoint = CGPoint(x: 0.0, y: 0.5) 
      self.frame = CGRect(x: frame.width - shadowWidth, y: 0, width: shadowWidth, height: frame.height) 
     } 
    } 

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

I aktualisiert @ NRitH Antwort und machte eine Erweiterung aus ihm auch so modifiziert werden, dass Sie mehrere Kanten manipulieren können in einem

gehen

Nutzung

myview.addShadow(to: [.top,.bottom], radius: 15.0)

extension UIView{ 

    func addShadow(to edges:[UIRectEdge], radius:CGFloat){ 

     let toColor = UIColor(colorLiteralRed: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0) 
     let fromColor = UIColor(colorLiteralRed: 188.0/255.0, green: 188.0/255.0, blue: 188.0/255.0, alpha: 1.0) 
     // Set up its frame. 
     let viewFrame = self.frame 
     for edge in edges{ 
      let gradientlayer   = CAGradientLayer() 
      gradientlayer.colors  = [fromColor.cgColor,toColor.cgColor] 
      gradientlayer.shadowRadius = radius 

      switch edge { 
      case UIRectEdge.top: 
       gradientlayer.startPoint = CGPoint(x: 0.5, y: 0.0) 
       gradientlayer.endPoint = CGPoint(x: 0.5, y: 1.0) 
       gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: gradientlayer.shadowRadius) 
      case UIRectEdge.bottom: 
       gradientlayer.startPoint = CGPoint(x: 0.5, y: 1.0) 
       gradientlayer.endPoint = CGPoint(x: 0.5, y: 0.0) 
       gradientlayer.frame = CGRect(x: 0.0, y: viewFrame.height - gradientlayer.shadowRadius, width: viewFrame.width, height: gradientlayer.shadowRadius) 
      case UIRectEdge.left: 
       gradientlayer.startPoint = CGPoint(x: 0.0, y: 0.5) 
       gradientlayer.endPoint = CGPoint(x: 1.0, y: 0.5) 
       gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height) 
      case UIRectEdge.right: 
       gradientlayer.startPoint = CGPoint(x: 1.0, y: 0.5) 
       gradientlayer.endPoint = CGPoint(x: 0.0, y: 0.5) 
       gradientlayer.frame = CGRect(x: viewFrame.width - gradientlayer.shadowRadius, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height) 
      default: 
       break 
      } 
      self.layer.addSublayer(gradientlayer) 
     } 

    } 

    func removeAllSublayers(){ 
     if let sublayers = self.layer.sublayers, !sublayers.isEmpty{ 
      for sublayer in sublayers{ 
       sublayer.removeFromSuperlayer() 
      } 
     } 
    } 

} 

Shadow

Verwandte Themen