2012-04-12 25 views
35

Wydajność zasysania QuartzCore .layer.shadow. Wydają się wymagać ponownego renderowania za każdym razem, gdy coś się zmienia, powodując opóźnienie wszystkiego.Najszybszy sposób na cienie w systemie iOS?

Gradient grafiki (dla cieni jednokierunkowych) - nie wygląda prawidłowo. jeśli gradient zmienia się z 0,3 alfa na 0, ma dziwny efekt, gdy "widzisz", że się zatrzymuje. Po prostu nie wygląda ładnie ani naturalnie. Może to nie jest dithered, ale jestem pewien, że słyszałem podstawowe gradienty grafiki. To dziwne, nie wiem.

Cień Coregraphics - trochę potrwa, aby renderować podczas ustawiania, ale poza tym świetna wydajność. Po prostu oczekujesz na pojawienie się widoku, ponieważ musi on najpierw renderować cień, to jest problem.

Muszę więc czegoś pomijać. Czy istnieje inna metoda, która wygląda dobrze i jest szybka zarówno w czasie renderowania, jak i wydajności?

Odpowiedz

100

Dodanie shadowPath powinno dać ogromny wzrost wydajności. Poniższy przykład zakłada, chcesz tylko cień na bokach widoku

CGPathRef path = [UIBezierPath bezierPathWithRect:view.bounds].CGPath; 
[view.layer setShadowPath:path]; 

EDIT: Na domyślnie CALayer rysuje cień podczas animacji, następujący kod pozwala buforować cień jako bitmapę i używać go zamiast przerysowywania go:

self.view.layer.shouldRasterize = YES; 
// Don't forget the rasterization scale 
// I spent days trying to figure out why retina display assets weren't working as expected 
self.view.layer.rasterizationScale = [UIScreen mainScreen].scale; 
+2

Awesome! Właściwość shouldRasterize powinna wystarczyć. Dziękuję Ci! – DZenBot

+1

rasteryzacjaScale także mnie złapała! Można by sobie wyobrazić, że domyślnie byłby oparty na skali ekranu, ale nie. : -/ – Dermot

+0

Miałem częściowo przezroczysty PNG z postrzępionymi krawędziami, które musiałem animować (oczywiście z cieniem). To było 2/3 ekranu, a więc sporo pikseli. To rozwiązanie wciąż działało bezbłędnie. :) – toblerpwn

8

ja często postrzegane przez ludzi za pomocą warstwy OGROMNY Performance Impact Zobacz do stworzenia zaokrąglony narożnik lub dropshadow. Coś takiego:

[v.layer setCornerRadius:30.0f]; 
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor]; 
[v.layer setBorderWidth:1.5f]; 
[v.layer setShadowColor:[UIColor blackColor].CGColor]; 
[v.layer setShadowOpacity:0.8]; 
[v.layer setShadowRadius:3.0]; 
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)]; 
..... 

Ma to OGROMNY wpływ na wydajność, zwłaszcza w cieniu. Umieszczenie takich widoków w UITableView (lub fakt, że wszystko, co się rusza) stworzy przewijanie w stylu androida, nie chcesz tego. Jeśli chcesz animować lub przesuwać widok, unikaj tworzenia zaokrąglonych narożników lub upuszczaj cienie w ten sposób!

Meet rdzeń graficzny
Utworzyłem proste UIView podklasy, aby pokazać, w jaki sposób osiągnąć ten sam rezultat w nieco inny sposób. Wykorzystuje Core Graphics do rysowania widoku, w przeciwieństwie do powyższego kodu, nie ma wpływu na wydajność.

Oto kod rysunek:

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef ref = UIGraphicsGetCurrentContext(); 

    /* We can only draw inside our view, so we need to inset the actual 'rounded content' */ 
    CGRect contentRect = CGRectInset(rect, _shadowRadius, _shadowRadius); 

    /* Create the rounded path and fill it */ 
    UIBezierPath *roundedPath = [UIBezierPath bezierPathWithRoundedRect:contentRect cornerRadius:_cornerRadius]; 
    CGContextSetFillColorWithColor(ref, _fillColor.CGColor); 
    CGContextSetShadowWithColor(ref, CGSizeMake(0.0, 0.0), _shadowRadius, _shadowColor.CGColor); 
    [roundedPath fill]; 

    /* Draw a subtle white line at the top of the view */ 
    [roundedPath addClip]; 
    CGContextSetStrokeColorWithColor(ref, [UIColor colorWithWhite:1.0 alpha:0.6].CGColor); 
    CGContextSetBlendMode(ref, kCGBlendModeOverlay); 

    CGContextMoveToPoint(ref, CGRectGetMinX(contentRect), CGRectGetMinY(contentRect)+0.5); 
    CGContextAddLineToPoint(ref, CGRectGetMaxX(contentRect), CGRectGetMinY(contentRect)+0.5); 
    CGContextStrokePath(ref); 
} 

Zobacz ten blog: http://damir.me/rounded-uiview-with-shadow-the-right-way

+0

Link do repozytorium git na tym blogu nie działa. Jak powinienem użyć tego na UICollectionViewCell? – trdavidson

+1

Dodaj powyższy drawrect wewnątrz twojej podklasy UICollectionViewCell @trdavidson –

+0

niesamowite! dzięki - to się udało – trdavidson

Powiązane problemy