2012-04-12 10 views
35

QuartzCore .layer.shadow's de alto rendimiento. Parecen necesitar ser re-renderizados cada vez que algo cambia, causando que todo se retrase.¿La forma más rápida de hacer sombras en iOS?

gradiente de Coregraphics (para sombras de 1 vía) - no se ve bien. si tu gradiente va de 0.3 alfa a 0, tiene un efecto extraño donde puedes 'verlo'. Simplemente no se ve bien, o natural. Tal vez no esté titubeante, pero estoy seguro de que escuché los gradientes gráficos centrales. Es extraño, no sé.

sombra Coregraphics: tómate un tiempo para renderizar como lo configuraste, pero por lo demás un gran rendimiento. Es solo ese segundo que estás esperando que aparezca una vista porque primero tiene que mostrar su sombra, ese es el problema.

Así que me falta algo. ¿Hay otro método que se ve bien, y es rápido tanto en tiempo de renderización como en rendimiento?

Respuesta

100

Agregar un shadowPath debería darle un impulso de rendimiento enorme. El siguiente ejemplo asume solo deseas la sombra en los lados de su vista

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

EDIT: Por defecto un CALayer dibuja una sombra durante las animaciones, el siguiente código permite almacenar en caché la sombra como un mapa de bits y reutilizarlo en lugar de volver a dibujar que:

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

impresionante! propiedad de shouldRasterize hizo el truco. ¡Gracias! – DZenBot

+1

rasterización ¡Scame también me sorprendió por un tiempo! Usted se imaginaría que se basaría en la escala de la pantalla, pero no. : -/ – Dermot

+0

Tenía un PNG parcialmente transparente con bordes dentados que tuve que animar (con una sombra, por supuesto). Fue 2/3 de la pantalla en tamaño, por lo que algunos píxeles. Esta solución todavía funcionó sin problemas. :) – toblerpwn

8

menudo he visto a gente usando la capa de enorme rendimiento de vista de impacto para crear una esquina redondeada o dropshadow. Algo como esto:

[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)]; 
..... 

Esto tiene un impacto en el rendimiento enorme, especialmente con la sombra. Al poner vistas como esta en una UITableView (o cualquier cosa que se mueva) crearemos una experiencia de desplazamiento android-ish, eso no es deseable. Si necesita animar o mover la vista, evite crear esquinas redondeadas o dejar caer sombras como esta por cualquier medio.

Gráficos Meet Core
que he creado un simple subclase UIView que le muestre la forma de lograr el mismo resultado de una manera ligeramente diferente. Utiliza los gráficos centrales para dibujar la vista y, a diferencia del código anterior, no afecta el rendimiento.

Aquí está el código de dibujo:

- (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); 
} 

Ver este blog: http://damir.me/rounded-uiview-with-shadow-the-right-way

+0

Parece que el enlace al repositorio de git en este blog ya no funciona. ¿Cómo debería usar esto en un UICollectionViewCell? – trdavidson

+1

Agregue el drawrect anterior dentro de su subclase de UICollectionViewCell @trdavidson –

+0

¡increíble! gracias - eso hizo el truco – trdavidson

Cuestiones relacionadas