我们希望在我们的iPhone应用中使用UITabBar,但有一个例外:我们有一个“同步”按钮,我希望在同步操作正在进行时旋转它。
问题似乎在于我如何实现选项卡栏 - 我想实现与 UITabBar 非常相似的效果,只需提供图标的 PNG 文件,然后利用 alpha 通道通过遮罩背景图像来创建正常和突出显示的状态。我使用 CALayer 的 mask 属性完成了这个目标:
// 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];
(注意:在上面的截图中,您可以看到我还添加了一个阴影层,但为了简单起见,我从代码中删除了它。当同步图标正在动画时,我会从遮罩层中移除阴影层,因此它不应该是相关的。)
要进行动画,我只需旋转遮罩层即可:
- (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
}
所以这一切都很好,除了性能。你可以看到我已经尝试了谷歌上关于栅格化图层/使其不透明的提示-没有帮助。
我认为我已经确定了遮罩层是罪魁祸首。当我取出遮罩层,只旋转fgLayer而不是它的遮罩时,性能非常好,尽管这肯定不是我想要的效果:
如果我在应用蒙版时旋转fgLayer
而不是蒙版同时,性能仍然像以前一样糟糕。
因此,如果每帧动画都必须重新合成蒙版导致速度变慢,是否有其他技术可以使用以实现类似的效果并具有更好的性能?使用路径而不是图像作为蒙版层?还是我必须降低到OpenGL或其他东西才能获得良好的性能?
更新:进一步强化了蒙版是减速的想法,我的同事建议尝试仅使用图像作为内容旋转CALayer,类似于上面的示例,没有蒙版,这样性能也很好。所以我只能做一个纯色(没有渐变),但这可能是一个很好的临时解决方案。我仍然希望能够以良好的性能旋转蒙版,因此欢迎提出建议:)
shouldRasterize
。这似乎使性能与没有遮罩时一样好。我“需要”一个遮罩的原因是为了可以用漂亮的渐变来“填充”简单的PNG图标,以增加视觉效果。默认的UITabBar也是这样做的,所以我想做同样的事情(但是用黄色)。 - Brent DillinghamshouldRasterize
,也许 CA 会采取shouldRasterize
提示并将每个子图层的遮罩操作合并为一个操作,从而使其无需为每个遮罩图层交换缓冲区。您是否尝试在两种情况下都打开 Instruments 中的“关闭屏幕颜色”选项,以查看 CA 进行了多少次渲染通道?如果我有时间,我会测试它,但是如果您比我更快,请告诉我。我想揭开这个黑魔法的神秘面纱。 :) - Nathan Eror