Мы хотели использовать UITabBar в нашем приложении для iPhone, но с одним исключением: у нас есть кнопка «синхронизация», которую я хотел повернуть во время операции синхронизации.
К сожалению, это означало необходимость создания настраиваемой панели вкладок, но это ни здесь, ни там: анимация, которую я реализовал с помощью Core Animation, выглядит потрясающе. Проблема в том, что при анимации это отрицательно сказывается на производительности всего остального с помощью анимации на экране: прокрутка UITableView, панорамирование MKMapView, удаление булавок и т. Д. Моим тестовым устройством является iPhone 4.
Проблема, похоже, заключается в том, как я реализовал панель вкладок - я хотел добиться чего-то очень похожего на UITabBar, где вы просто предоставляете PNG для значка, и он использует альфа-канал для создания нормальных и выделенных состояний с помощью маскировка фонового изображения. Я сделал это с помощью свойства mask
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];
(Примечание: на скриншоте выше вы можете видеть, что я также добавил теневой слой, но для простоты я удалил его из кода. Я удаляю теневой слой со значка синхронизации, когда он анимируется, поэтому он не должен ' не актуально.)
Для анимации я просто вращаю слой маски:
- (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
}
Так что все это прекрасно работает, кроме производительности. Вы можете видеть, что я уже пробовал всплывающие в Google советы о растеризации слоев / создании их непрозрачности - не помогло.
Я думаю, что определил слой маски как виновника. Когда я вынимаю слой маски и просто поворачиваю fgLayer
вместо его маски, производительность замечательна, хотя это, конечно, не тот эффект, которого я добиваюсь:
Производительность так же плоха, как и раньше, если я поверну fgLayer
вместо маски , а маска будет применена.
Итак, если необходимость перекомпоновки маски для каждого кадра анимации замедляется, есть ли другие методы, которые я могу использовать для достижения аналогичного эффекта, который будет иметь более высокую производительность? Использование пути вместо изображения для маскирующего слоя? Или мне придется перейти на OpenGL или что-то еще, чтобы получить хорошую производительность?
ОБНОВЛЕНИЕ: Еще больше подкрепляя идею о том, что маска - это замедление, мой коллега предложил попытаться повернуть CALayer только с изображением в качестве содержимого - так похоже на мой пример выше без маски - - и производительность была так же хороша. Так что я могу сделать только сплошной цвет (без градиента), но это может быть хорошим промежуточным решением. Я все еще хотел бы добиться поворота маски с хорошей производительностью, поэтому предложения приветствуются:)