Так что хорошо, что вы здесь все выяснили, но в вашем ответе на свой вопрос есть некоторые неточности. Позвольте мне исправить несколько вещей:
Свойство фрейма может быть анимированным - только без явной анимации. Если вы сделаете следующее для слоя, отличного от корневого слоя представления, рамка будет анимирована очень хорошо:
[CATransaction begin];
[CATransaction setAnimationDuration:2.0f];
[animationLayer setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
[CATransaction commit];
Помните, что установка свойства на слое оживляет изменение этого свойства по умолчанию . Фактически вы должны отключить анимацию при изменении свойства, если вы не хотите, чтобы оно анимировалось. (Конечно, это верно только в том случае, если вы анимируете слой, отличный от корневого слоя представления.) Вы правильно анимируете и положение, и границы, если вам нужно использовать явную анимацию.
Вы можете анимировать кадр в UIView, используя неявную анимацию:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:3.0f];
[[self view] setFrame:CGRectMake(45.0f, 45.0f, 100.0f, 100.0f)];
[UIView commitAnimations];
Это будет анимация от текущего кадра вида (границы и положение) до x = 45.0, y = 45.0, w = 100.0, h = 100.0.
Возможно, вы также неправильно понимаете разницу между анимацией и слоем. Вы добавляете анимацию к слоям, но добавление анимации к слою не устанавливает автоматически свойство, которое вы анимируете.
CALayers - это модельные объекты. Они содержат информацию о слое, который в итоге отображается на экране. Вы должны установить свойство слоя, если хотите, чтобы это свойство действительно имело это значение. Если вы просто анимируете свойство, оно будет только визуальным представлением, а не фактическим - то есть именно поэтому значение возвращается к исходному значению слоя, потому что вы фактически никогда не меняли его.
Что приводит меня к следующему пункту. Вы сказали:
Использовать "animation.removedOnCompletion =
НЕТ; animation.fillMode =
kCAFillModeForwards; "чтобы убедиться, что
значения не сбрасываются в конце
анимации
Это не совсем верно. Эти два значения просто приводят к тому, что анимация остается на своей конечной позиции визуально , однако фактические значения слоя не изменились. Они все те же значения, которые были при запуске анимации. В целом (за некоторыми исключениями) вы не хотите использовать эти два параметра, потому что они только визуальные . То, что вы хотите, это на самом деле установить значение слоя для свойства, которое вы анимируете.
Скажем, например, что вы хотите анимировать положение вашего слоя, используя явную анимацию. Вот код, который вы хотите:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
[animation setFromValue:[NSValue valueWithCGPoint:CGPointMake(70.0f, 70.0f)]];
[animation setToValue:[NSValue valueWithCGPoint:CGPointMake(150.0f, 150.0f)]];
[animation setDuration:2.0f];
// Actually set the position on the *layer* that you want it to be
// when the animation finishes.
[animationLayer setPosition:CGPointMake(150.0f, 150.0f)];
// Add the animation for the position key to ensure that you
// override the animation for position changes with your animation.
[animationLayer addAnimation:animation forKey:@"position"];
Вы также можете рассмотреть группировку анимации. С группой анимации вы можете сгруппировать несколько анимаций вместе, а затем контролировать, как они связаны друг с другом. В вашем случае продолжительность анимации границ и позиции одинакова, и поэтому то, что вы пытаетесь сделать, будет работать без группы, но если вы хотите сместить начало анимации, например, вам не нужна позиция анимация запускается до секунды или двух в кадре анимации, вы можете пошатнуть их, установив beginTime значение анимации позиции.
Наконец, мне было бы любопытно узнать, почему вы не можете использовать неявные анимации, доступные в UIView. Я использую их в подавляющем большинстве кода Core Animation, который я пишу, и не понимаю, почему это не сработает в вашей ситуации.
С уважением.