2010-02-21 17 views
24

Mam podklasę uiview, gdzie próbuję narysować zaokrąglony prostokąt z cieniem. Chociaż rysuje oba elementy, widzę cień przez zaokrąglone wypełnienie prostokąta. Jestem nowy w CG, więc prawdopodobnie brakuje mi czegoś prostego (choć nie wydaje się to być alfa wypełnienia, która jest ustawiona na 1). Oto kod prostownika.UIView z zaokrąglonym prostokątem i cieniem: cień pojawia się nad prostokątem

- (void)drawRect:(CGRect)rect { 
    // get the contect 
CGContextRef context = UIGraphicsGetCurrentContext(); 

//for the shadow, save the state then draw the shadow 
CGContextSaveGState(context); 
    CGContextSetShadow(context, CGSizeMake(4,-5), 10); 



//now draw the rounded rectangle 
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0); 

//since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame 
CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30); 
CGFloat radius = self.cornerRadius; 
// the rest is pretty much copied from Apples example 
CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); 
CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); 

// Start at 1 
CGContextMoveToPoint(context, minx, midy); 
// Add an arc through 2 to 3 
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
// Add an arc through 4 to 5 
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
// Add an arc through 6 to 7 
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
// Add an arc through 8 to 9 
CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
// Close the path 
CGContextClosePath(context); 
// Fill & stroke the path 
CGContextDrawPath(context, kCGPathFillStroke); 

//for the shadow 
    CGContextRestoreGState(context); 
} 
+1

Przeczytaj tę blogu http://bynomial.com/blog/?p=52&cpage=1#comment-1115. Odpowiada, jak to zrobić. –

+0

rozwiązanie tutaj opisane jest najlepsze dla mnie, ponieważ pokazuje mi, jak używać niestandardowego obrazu (z maskToBounds = YES), a także cienia. dzięki! – Mark

+0

@John: Wielkie dzięki za link, kolego ... Pomógł mi zacząć. :) – viral

Odpowiedz

16

Nie sądzę, że można to zrobić za jednym razem. Hmm, zmieniłem twój kod w następujący sposób, co wydaje się działać.

- (void)drawRect:(CGRect)rect 
{ 
    // get the contect 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    //now draw the rounded rectangle 
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
    CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 0.0); 

    //since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame 
    CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30); 
    CGFloat radius = 45; 
    // the rest is pretty much copied from Apples example 
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); 
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); 

    { 
     //for the shadow, save the state then draw the shadow 
     CGContextSaveGState(context); 

     // Start at 1 
     CGContextMoveToPoint(context, minx, midy); 
     // Add an arc through 2 to 3 
     CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
     // Add an arc through 4 to 5 
     CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
     // Add an arc through 6 to 7 
     CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
     // Add an arc through 8 to 9 
     CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
     // Close the path 
     CGContextClosePath(context); 

     CGContextSetShadow(context, CGSizeMake(4,-5), 10); 
     CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 

     // Fill & stroke the path 
     CGContextDrawPath(context, kCGPathFillStroke); 

     //for the shadow 
     CGContextRestoreGState(context); 
    } 

    { 
     // Start at 1 
     CGContextMoveToPoint(context, minx, midy); 
     // Add an arc through 2 to 3 
     CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
     // Add an arc through 4 to 5 
     CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
     // Add an arc through 6 to 7 
     CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
     // Add an arc through 8 to 9 
     CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
     // Close the path 
     CGContextClosePath(context); 

     CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
     CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);  

     // Fill & stroke the path 
     CGContextDrawPath(context, kCGPathFillStroke); 
    } 
} 
+0

Świetnie, dzięki. Ma wiele sensu: narysujesz prostokąt, narysujesz cień, który znajduje się powyżej zaokrąglonego prostokąta, więc kończysz rysując ponownie prostokąt. Jedna uwaga na kodzie. Ustawiłem tło widoku do wyczyszczenia w mojej instrukcji init. Powyższy kod działa z każdym innym tłem, ale z jasnym tłem musiałem ustawić kolor wypełnienia zanim pierwszy prostokąt zostanie pogłaskany i wypełniony. – Martin

+0

Przeczytałem, że można rozszerzyć obszar renderowanej warstwy, aby nie była przycięta przez ramkę widoku. Użyj: layer.bounds = CGRectMake (-1, -1,102,102) ... jeśli twój widok jest 100x100, a cień jest przesunięciem pikselowym itd. Masz pomysł. –

15

Spróbuj tego po zaimportowaniu QuartzCore/QuartzCore.h

yourView.layer.shadowColor = [[UIColor blackColor] CGColor]; 
yourView.layer.shadowOffset = CGSizeMake(10.0f, 10.0f); 
yourView.layer.shadowOpacity = 1.0f; 
yourView.layer.shadowRadius = 10.0f; 
+1

Zwróć uwagę, że jest to obsługiwane przez iOS 3.2 i wyżej tylko –

+1

to nie działa z zaokrąglonymi narożnikami za pomocą _maskToBounds i setCornerRadius_. –

+2

To rozwiązanie spowalnia zauważalnie całą aplikację ... – Ondrej

39
- (void)drawRect:(CGRect)rect 
{ 
    self.layer.masksToBounds = NO; 
    self.layer.shadowColor = [[UIColor whiteColor] CGColor]; 
    self.layer.shadowOffset = CGSizeMake(0,2); 
    self.layer.shadowRadius = 2; 
    self.layer.shadowOpacity = 0.2; 

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(20, 20)]; 
    [[UIColor blackColor] setFill]; 

    [path fill]; 
} 
+0

Bardzo pomocne, dzięki! – Gabriel

+0

Jedynym zastrzeżeniem jest upewnienie się, że tło twojego widoku jest ustawione na [UIColor clearColor], w przeciwnym razie cienie będą rysowane wokół ramki widoku, ignorując zaokrąglone rogi. – Julian

+2

Nieużyteczne i nadmiarowe jest ustawienie właściwości warstwy w elemencie drawRect :, ponieważ nie zmieniają się, chyba że je zmienisz. Przenieś te połączenia (np. W init ...). – millenomi

Powiązane problemy