2013-03-29 13 views
18

Ho implementato con successo il disegno un'ombra intorno al mio UIView come questo:Disegna ombra solo da 3 lati di UIView

block1.layer.masksToBounds = NO; 
block1.layer.shadowOffset = CGSizeMake(0, 0); 
block1.layer.shadowRadius = 1; 
block1.layer.shadowOpacity = 0.7; 

E adesso che succede è che ho un rettangolare UIView e vorrei richiamare l'ombra intorno tre lati, lasciando il lato inferiore senza l'ombra.

So che devo specificare il block1.layer.shadowPath creando un nuovo UIBezierPath ma non sono sicuro di come farlo.

Ovviamente, impostare layer.shadowOffset non farà il trucco per me.

Grazie in anticipo!

risposta

47

So che dici che l'impostazione layer.shadowOffset non funzionerà per te, ma ti è permesso inserire valori negativi quindi impostarlo su layer.shadowOffset = CGSizeMake(0.0, -2.0) si avvicinerebbe all'effetto che stai cercando, ma ovviamente mi aspetto che tu lo voglia essere anche sui tre lati.

Quindi eccoci con layer.shadowPath!

UIView *block1 = [[UIView alloc] initWithFrame:CGRectMake(32.0, 32.0, 128.0, 128.0)]; 
[block1 setBackgroundColor:[UIColor orangeColor]]; 
[self.view addSubview:block1]; 

block1.layer.masksToBounds = NO; 
block1.layer.shadowOffset = CGSizeMake(0, 0); 
block1.layer.shadowRadius = 1; 
block1.layer.shadowOpacity = 0.7; 

UIBezierPath *path = [UIBezierPath bezierPath]; 

// Start at the Top Left Corner 
[path moveToPoint:CGPointMake(0.0, 0.0)]; 

// Move to the Top Right Corner 
[path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame), 0.0)]; 

// Move to the Bottom Right Corner 
[path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame), CGRectGetHeight(block1.frame))]; 

// This is the extra point in the middle :) Its the secret sauce. 
[path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame)/2.0, CGRectGetHeight(block1.frame)/2.0)]; 

// Move to the Bottom Left Corner 
[path addLineToPoint:CGPointMake(0.0, CGRectGetHeight(block1.frame))]; 

// Move to the Close the Path 
[path closePath]; 

block1.layer.shadowPath = path.CGPath; 

E per darvi un'idea di cosa sta succedendo, qui è il percorso dell'ombra reale appena disegnata :)

enter image description here

La sua possibile spostare solo quel punto di mezzo in più prima o dopo le altre linee per scegliere quale lato verrà omesso.

+0

Questo non funziona con grande 'shadowRadius' come si può sanguinare fuori area triangolare creata con il' shadowPath '. –

+0

È vero, puoi regolare il percorso in modo che sia un po 'più breve del resto del quadrato in quei modelli. –

2

Aggiornamento Ryan Poolos risposta a Swift 3.0

Grazie alla Ryan Poolos

class sampleViewController: UIViewController { 
    var block1: UIView! = nil 

    override func viewDidLoad() { 

    super.viewDidLoad() 
    block1 = UIView(frame: CGRect(x: 32.0, y: 32.0, width: 128.0, height: 128.0)) 
    block1.backgroundColor = UIColor.orange 
    self.view.addSubview(block1) 

    block1.layer.masksToBounds = false 
    block1.layer.shadowOffset = CGSize(width: 0.0, height: 0.0) 
    block1.layer.shadowRadius = 1.0 
    block1.layer.shadowOpacity = 0.7 

    let path = UIBezierPath() 

    // Start at the Top Left Corner 
    path.move(to: CGPoint(x: 0.0, y: 0.0)) 

    // Move to the Top Right Corner 
    path.addLine(to: CGPoint(x: block1.frame.size.width, y: 0.0)) 

    // Move to the Bottom Right Corner 
    path.addLine(to: CGPoint(x: block1.frame.size.width, y: block1.frame.size.height)) 

    // This is the extra point in the middle :) Its the secret sauce. 
    path.addLine(to: CGPoint(x: block1.frame.size.width/2.0, y: block1.frame.size.height/2.0)) 

    // Move to the Bottom Left Corner 
    path.addLine(to: CGPoint(x: 0.0, y: block1.frame.size.height)) 

    path.close() 

    block1.layer.shadowPath = path.cgPath 

    } 
} 

Risultato:

enter image description here

0

Un po 'di miglioramento per altre risposte, grazie a Ashok R per il codice swift.

Poiché stavamo creando una vista triangolare sullo sfondo della vista con l'ombra su tutti i lati e un triangolo bianco sui lati non è necessario.

Si interrompe in caso di viste con larghezza comparativamente maggiore di altezza.

enter image description here

Una soluzione sarà spostare il percorso per la riga dove ombra senza un po 'verso quel lato di vista, invece di creare completamente vista Path triangolare.

ho creato un'estensione per questo -

extension UIView { 
    func addshadow(top: Bool, 
        left: Bool, 
        bottom: Bool, 
        right: Bool, 
        shadowRadius: CGFloat = 2.0) { 

     self.layer.masksToBounds = false 
     self.layer.shadowOffset = CGSize(width: 0.0, height: 0.0) 
     self.layer.shadowRadius = shadowRadius 
     self.layer.shadowOpacity = 1.0 

     let path = UIBezierPath() 
     var x: CGFloat = 0 
     var y: CGFloat = 0 
     var viewWidth = self.frame.width 
     var viewHeight = self.frame.height 

     // here x, y, viewWidth, and viewHeight can be changed in 
     // order to play around with the shadow paths. 
     if (!top) { 
      y+=(shadowRadius+1) 
     } 
     if (!bottom) { 
      viewHeight-=(shadowRadius+1) 
     } 
     if (!left) { 
      x+=(shadowRadius+1) 
     } 
     if (!right) { 
      viewWidth-=(shadowRadius+1) 
     } 
     // selecting top most point 
     path.move(to: CGPoint(x: x, y: y)) 
     // Move to the Bottom Left Corner, this will cover left edges 
     /* 
     |☐ 
     */ 
     path.addLine(to: CGPoint(x: x, y: viewHeight)) 
     // Move to the Bottom Right Corner, this will cover bottom edge 
     /* 
     ☐ 
     - 
     */ 
     path.addLine(to: CGPoint(x: viewWidth, y: viewHeight)) 
     // Move to the Top Right Corner, this will cover right edge 
     /* 
     ☐| 
     */ 
     path.addLine(to: CGPoint(x: viewWidth, y: y)) 
     // Move back to the initial point, this will cover the top edge 
     /* 
     _ 
     ☐ 
     */   
     path.close() 
     self.layer.shadowPath = path.cgPath 
    } 

e impostare il valore booleano vero per qualunque lato si vuole l'ombra appaia

myView.addshadow(top: false, left: true, bottom: true, right: true, shadowRadius: 2.0)

// raggio ombra è facoltativo sopra ed è impostato come predefinito su 2.0

enter image description here

o myView.addshadow(top: true, left: true, bottom: true, right: true, shadowRadius: 2.0) enter image description here

o myView.addshadow(top: false, left: false, bottom: true, right: true, shadowRadius: 2.0)

enter image description here

+0

Come dare cornerRadius con ombra. Si prega di aggiornare la risposta –