Queríamos utilizar una UITabBar en nuestra aplicación para iPhone, pero con una excepción: tenemos un botón de "sincronización" que quería girar mientras se realiza la operación de sincronización.Animación principal Animación de máscara CALayer
Desafortunadamente esto significaba tener que crear una barra de pestañas a medida, pero eso es no viene al caso: la animación he implementado usando Core Animation se ve impresionante. El problema es que al animar, afecta negativamente el rendimiento de todo lo demás mediante la animación en la pantalla: desplazamiento UITableView, panorámica MKMapView y pin gotas, etc. Mi dispositivo de prueba es un iPhone 4.
El problema parece ser cómo Implementé la barra de pestañas. Quería lograr algo muy similar a UITabBar, donde solo proporcionas un PNG para el ícono y usa el canal alfa para crear los estados normal y resaltado enmascarando una imagen de fondo. He logrado esto con mask
propiedad de CALayer:
// Inside a UIView subclass' init method...
// Create the mask layer by settings its contents as our PNG icon.
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = CGRectMake(0, 0, 31, 31);
maskLayer.contentsGravity = kCAGravityCenter;
maskLayer.contentsScale = [[UIScreen mainScreen] scale];
maskLayer.rasterizationScale = [[UIScreen mainScreen] scale];
maskLayer.contents = (id)symbolImage.CGImage;
maskLayer.shouldRasterize = YES;
maskLayer.opaque = YES;
fgLayer = [[CALayer layer] retain];
fgLayer.frame = self.layer.frame;
fgLayer.backgroundColor = [UIColor colorWithImageNamed:@"tabbar-normal-bg.png"].CGColor;
fgLayer.mask = maskLayer; // Apply the mask
fgLayer.shouldRasterize = YES;
fgLayer.opaque = YES;
[self.layer addSublayer:fgLayer];
(Nota: en la pantalla de arriba se puede ver también he añadido una capa de sombra, pero para simplificar Quité que a partir del código quito la capa de sombra de. . el icono de sincronización cuando está animando, por lo que no debe ser relevante)
animar, me basta con girar la capa de máscara:
- (void)startAnimating {
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath: @"transform"];
CATransform3D transform = CATransform3DMakeRotation(RADIANS(179.9), 0.0, 0.0, 1.0);
animation.toValue = [NSValue valueWithCATransform3D:transform];
animation.duration = 5;
animation.repeatCount = 10000;
animation.removedOnCompletion = YES;
[fgLayer.mask addAnimation:animation forKey:@"rotate"]; // Add animation to the mask
}
así que todo esto funciona genial, excepto para el rendimiento. Puedes ver que ya probé algunos consejos que aparecieron en Google sobre rasterizar capas/hacerlas opacas, no ha ayudado.
Creo que he identificado la capa de máscara como la culpable. Cuando llevo a cabo la capa de máscara y Basta girar la fgLayer
en lugar de su máscara, el rendimiento es maravillosa, aunque ciertamente no es el afecto Voy para:
rendimiento también es tan malo como antes si giro fgLayer
en lugar de la máscara mientras que se aplica la máscara.
Entonces, si al volver a unir la máscara cada fotograma de la animación es la ralentización, ¿hay otras técnicas que pueda utilizar para lograr un efecto similar que tenga un mejor rendimiento? ¿Usa una ruta en lugar de una imagen para la capa de máscara? ¿O tendré que pasar a OpenGL o algo para obtener un buen rendimiento?
ACTUALIZACIÓN: reforzando aún más la idea de que la máscara es la desaceleración, mi compañero de trabajo sugirió tratando de girar una CALayer con sólo la imagen como el contenido - de modo similar al ejemplo anterior w máscara/oa - y el rendimiento también fue bueno de esa manera. Así que realmente solo puedo hacer un color sólido como ese (sin degradado), pero puede ser una buena solución provisional. Todavía me encanta para lograr la rotación de una máscara con un buen rendimiento aunque, por lo sugerencia bienvenida :)
La segunda parte de su respuesta fue la solución: debería haber estado configurando 'shouldRasterize' en la capa superior en lugar de las subcapas. Esto parece haber hecho que el rendimiento sea tan bueno como sin la máscara. La razón por la que "necesito" una máscara es para poder "llenar" los iconos PNG simples con un degradado agradable para agregar interés visual. El UITabBar predeterminado hace esto, por lo que quería hacer lo mismo (pero con amarillo). –
Cool, Brent. Me alegro de que haya sido así de simple. Si obtiene alguna idea del * por qué * del asunto, me gustaría saberlo. ;-) –
Me encantaría saber por qué también. Además, me encantaría saber * cómo * rasterizar la capa superior realmente mejora el rendimiento de una animación de máscara. Sigue haciendo exactamente lo que yo quiero: la imagen del degradado de respaldo permanece estacionaria, mientras que la máscara está girando. ¿Está realmente precomputando el mapa de bits para cada cuadro antes de que comience la animación? Parece magia. En este caso, me gusta la magia. :) –