CABasicAnimation с каналом CALayer не анимирует
Я пытаюсь анимацию перехода CALayer из обычных углов в закругленные углы. Я хочу только округлить верхние углы, поэтому я использую UIBezierPath. Здесь код:
UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight;
UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)];
UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0f, 0.0f)];
CAShapeLayer* layer = [CAShapeLayer layer];
layer.frame = self.bounds;
layer.path = oldPath.CGPath;
self.layer.mask = layer;
CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"];
[a setDuration:0.4f];
[a setFromValue:(id)layer.path];
[a setToValue:(id)newPath.CGPath];
layer.path = newPath.CGPath;
[layer addAnimation:a forKey:@"path"];
Но когда я запускаю это, углы округляются, но анимации нет - это происходит мгновенно. Я видел некоторые подобные вопросы здесь, на SO, но они не решили мою проблему.
Анимация iPhone CALayer
Анимация свойства shadowPath CALayer
Я уверен, что я просто делаю одну мелочь неправильно, что вызывает проблему, но для жизни меня я не могу понять.
Решение:
- (void)roundCornersAnimated:(BOOL)animated {
UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight;
UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)];
UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0001f, 0.0001f)];
CAShapeLayer* layer = [CAShapeLayer layer];
layer.frame = self.bounds;
self.layer.mask = layer;
if(animated) {
CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"];
[a setDuration:0.4f];
[a setFromValue:(id)oldPath.CGPath];
[a setToValue:(id)newPath.CGPath];
layer.path = newPath.CGPath;
[layer addAnimation:a forKey:@"path"];
} else {
layer.path = newPath.CGPath;
}
}
Действительно, все, что мне нужно было сделать, это установить правильное значение "от" для анимации.
Ответы
Ответ 1
Мне кажется, что вы создаете слой с фигурой, который не имеет пути, а затем пытается оживить добавление пути к нему. Формы слоев являются особым случаем и не работают таким образом.
У вас должен быть путь в слое формы до и после анимации, и путь должен иметь одинаковое количество точек в нем до и после.
Вам нужно будет создать закругленный прямоугольник с радиусом угла 0 (вручную, используя ряд сторон и угловых дуг), а затем построить новый путь с ненулевыми радиусами для углов, которые вы хотите округлить и установить этот путь как ваша анимация.
Даже это может не сработать, потому что путь должен иметь точно такое же количество точек в нем, и я подозреваю, что дуги упростят точки, когда радиус равен нулю.
Я только что нашел вызов UIBezierPath, который создаст прямоугольник, в котором вы можете выбрать, какие углы округлить. Вызов bezierPathWithRoundedRect: byRoundingCorners: cornerRadii:
Это создаст прямоугольник с таким количеством закругленных углов, как вам нравится. Однако я не уверен, что он будет работать для анимации пути. Возможно, вам потребуется запросить, чтобы все углы были закруглены с двумя не закругленными углами, установленными на нулевой радиус. Таким образом, вы МОЖЕТЕ получить путь с тем же количеством точек в нем, что и округленный прямоугольник, так что анимация пути работает правильно. Вам придется попробовать.
Ответ 2
Попробуйте поставить:
layer.path = newPath.CGPath;
после
[layer addAnimation:a forKey:@"path"];