2013-03-29 11 views
18

Mam pomyślnie wdrożonych rysunek cień wokół mojego UIView tak:Draw cień tylko z 3 stron UIView

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

Co teraz się dzieje, mam prostokątny UIView i chciałbym, aby narysować cień wokół to trzy boki, pozostawiając po boku tę stronę.

Wiem, że muszę określić block1.layer.shadowPath, tworząc nowy UIBezierPath, ale nie jestem pewien, jak to zrobić.

Oczywiście ustawienie layer.shadowOffset nie pomoże mi.

Z góry dziękuję!

Odpowiedz

47

wiem mówisz ustawienie layer.shadowOffset nie będzie pracować dla Ciebie, ale masz prawo do wprowadzenia wartości ujemnych więc ustawienie go layer.shadowOffset = CGSizeMake(0.0, -2.0) by zbliżyć się do efektu, którego szukasz, ale oczywiście mogę się spodziewać chcesz go być nawet po trzech stronach.

Tak, więc idziemy z 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; 

i dać ci pomysł, co się dzieje, tutaj jest rzeczywista ścieżka cień po prostu wyciągnął :)

enter image description here

Jest to możliwe tylko przesunąć ten dodatkowy punkt środkowy przed lub po pozostałe linie do wyboru, która strona zostanie pominięta.

+0

to nie działa z większej 'shadowRadius' ponieważ może krwawić poza trójkątnym obszarze utworzonego z' shadowPath '. –

+0

Prawda, można ustawić ścieżkę, aby była nieco krótsza niż reszta kwadratu w tych rzutach. –

2

Aktualizacja Ryan Poolos odpowiedzi do Swift 3,0

Dzięki 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 

    } 
} 

Wynik:

enter image description here

0

Trochę poprawy dla innych odpowiedzi, dzięki Ashok R dla kodu szybkiego.

Ponieważ tworzyliśmy widok trójkątny w tle widoku z cieniem ze wszystkich stron, a biały trójkąt na cieniach bocznych nie jest potrzebny.

Zrywa się w przypadku widoków o szerokości porównywalnie większej niż wysokość.

enter image description here

Rozwiązaniem będzie zmieniać ścieżkę do linii, w której nie jest potrzebne cień nieco ku tej stronie widzenia zamiast tworzenia trójkątną ścieżkę widok całkowicie.

Stworzyłem przedłużenie tego -

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 
    } 

i ustawić wartość logiczną prawdziwą dla której strony chcesz cień pojawiać

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

// promień cień jest opcjonalny powyżej i jest ustawiony domyślnie na 2.0

enter image description here

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

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

enter image description here

+0

Jak podać rogu Radius z cienia. Zaktualizuj swoją odpowiedź –