CATransaction: Изменения слоя, но не оживляют

Я пытаюсь анимировать часть пользовательского интерфейса в приложении iPad, когда пользователь нажимает кнопку. У меня есть этот код в моем методе действий. Он работает в том смысле, что пользовательский интерфейс меняет то, что я ожидаю, но он не оживляет изменений. Он просто сразу меняется. Я должен что-то упустить:

- (IBAction)someAction:(id)sender {
    UIViewController *aViewController = <# Get an existing UIViewController  #>;
    UIView *viewToAnimate = aViewController.view;
    CALayer *layerToAnimate = viewToAnimate.layer;

    [CATransaction begin];
    [CATransaction setAnimationDuration:1.0f];

    CATransform3D rotateTransform = CATransform3DMakeRotation(0.3, 0, 0, 1);
    CATransform3D scaleTransform = CATransform3DMakeScale(0.10, 0.10, 0.10);
    CATransform3D positionTransform = CATransform3DMakeTranslation(24, 423, 0);
    CATransform3D combinedTransform = CATransform3DConcat(rotateTransform, scaleTransform);
    combinedTransform = CATransform3DConcat(combinedTransform, positionTransform);
    layerToAnimate.transform = combinedTransform;

    [CATransaction commit];

    // rest of method...
}

Я попробовал упростить анимацию, чтобы просто изменить прозрачность (например), и она все равно не будет анимироваться. Прозрачность просто меняется мгновенно. Это заставляет меня думать, что что-то не настроено должным образом.

Любые подсказки были бы полезны!

Ответы

Ответ 1

Анимация на корневом уровне представления отключена по умолчанию. Попробуйте вместо этого применить преобразование к представлению, например. [view setTransform: CGTransform3D...]. Если вы должны сделать это на уровне уровня, добавьте слой к корневому слою и вместо этого выполните свои преобразования. Также анимационный блок представления [UIView beginAnimations...] влияет только на анимацию свойств представления - в отличие от свойств слоя.

Update:

Итак, вот как будет выглядеть ваш код с явной анимацией (CATransaction не требуется)

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
CATransform3D rotateTransform = CATransform3DMakeRotation(0.3, 0, 0, 1);
CATransform3D scaleTransform = CATransform3DMakeScale(0.10, 0.10, 0.10);
CATransform3D positionTransform = CATransform3DMakeTranslation(24, 423, 0);
CATransform3D combinedTransform = CATransform3DConcat(rotateTransform, scaleTransform);
combinedTransform = CATransform3DConcat(combinedTransform, positionTransform);
[anim setFromValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
[anim setToValue:[NSValue valueWithCATransform3D:combinedTransform]];
[anim setDuration:1.0f];

[layerToAnimate addAnimation:anim forKey:nil];

Имейте в виду, что это только выполняет анимацию. Вы действительно должны установить свойство преобразования слоя с вызовом:

[layerToAnimate setTransform:combinedTransform];

. В противном случае он просто вернется в исходное положение.

Свойства слоя анимируются неявно, когда вы их устанавливаете, за исключением случаев, когда вы анимируете корневой слой представления. В этом случае анимация отключена по умолчанию, и я обнаружил, что то, что мне всегда нужно делать, - это анимировать представление, а не слой, когда меня интересует анимация корня. Итак, это означает, что вызов любого слоя в вашем дереве слоев, который приводит к изменению свойства, будет анимироваться неявно. Например:

CALayer *root = [view layer];

CALayer *sublayer = [[root sublayers] objectAtIndex:0];

[sublayer setTransform:combinedTransform];

Это единственный способ, которым я знаю (знаю), что вы действительно можете использовать неявную анимацию на слое. Однако, что указывает ваш код, вы можете включить анимацию слоя для корневого слоя, просто разместив изменения в слое в блоке анимации UIView. Это довольно интересно и удобно. Это довольно полезное открытие.

Возможно, это где-то похоронено в документах, но мне еще не удалось его встретить.

Ответ 2

Настройка вашего делегата layerToAnimate для вашего rootView.layer работает:

viewToAnimate.layer.delegate = rootView.layer;

Предполагая, что вы добавите вид/слой в корневой вид/слой. Невозможно найти, где это изменилось, использование неявных анимаций просто для работы.

Ответ 3

Оказывается, вы можете включить анимацию слоя для корневого слоя, установив его свойство delegate равным nil. Я не знаю, хорошая ли практика.