Как я могу использовать пользовательскую анимацию для onOrderOut в Core Animation?

Core Animation позволяет настраивать анимацию, реализуя метод actionForKey в вашем классе на основе CALayer:

- (id<CAAction>)actionForKey:(NSString *)key {
    // Custom animations
    return [super actionForKey:key];
}

Затем я могу создать анимацию и вернуть ее для действия onOrderIn (т.е. когда слой добавляется к другому слою). Это прекрасно работает. Если я сделаю то же самое для onOrderOut (т.е. слой удаляется из его суперслоя), возвращенная анимация игнорируется, и вместо нее применяется анимация по умолчанию.

Моя цель - увеличить (onOrderIn) и уменьшить (onOrderOut) слой:

- (id<CAAction>)actionForKey:(NSString *)key {

    if ([key isEqualToString:@"onOrderIn"] || [key isEqualToString:@"onOrderOut"]) {
        CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        a.duration = 0.25;
        a.removedOnCompletion = NO;
        a.fillMode = kCAFillModeBoth;

        if ([key isEqualToString:@"onOrderIn"]) {
            a.fromValue = [NSNumber numberWithFloat:0.0];
            a.toValue = [NSNumber numberWithFloat:1.0];
        } else {
            a.fromValue = [NSNumber numberWithFloat:1.0];
            a.toValue = [NSNumber numberWithFloat:0.0];
        }

        return a;
    }

    return [super actionForKey:key];
}

Увеличение работает, уменьшение - нет. Вместо этого используется анимация постепенного исчезновения по умолчанию.

Код может содержать опечатки, поскольку я набираю его на другом компьютере.

Кто-нибудь может помочь?


person Lemming    schedule 28.10.2008    source источник


Ответы (2)


Цитата Джона Харпера из списка рассылки quartz-dev:

Существует фундаментальная проблема с возвратом любой анимации для ключа onOrderOut - к тому времени, когда анимация должна быть запущена, слой уже не находится в дереве, поэтому он не имеет никакого эффекта. Таким образом, onOrderOut бесполезен для запуска анимации; это может быть полезно для запуска другого кода, когда слои удаляются из дерева.

Лучшее решение, которое я нашел для этого (при условии, что переход затухания по умолчанию для родительского элемента - это не то, что вы хотите, а это часто не так), - это добавить пользовательские анимации для применения желаемого эффекта удаления в анимации didStop делегировать, фактически удалить слой. Часто бывает удобно создать одну группу анимаций с установленным свойством делегата и fillMode = forwards, deletedOnCompletion = NO, чтобы вы могли удалить слой в конце анимации без возможности того, что слой все еще будет виден в его нормальном состоянии. .

Если вы делаете много таких случаев, легко написать общий суперкласс, который запускает анимацию, устанавливает делегата анимации для класса и реализует + animationDidStop: для удаления слоя без включенной анимации. Это восстанавливает природу CoreAnimation «запустил и забыл», которая, как вы надеялись, будет присутствовать в реализации по умолчанию.

person tjw    schedule 16.08.2009
comment
Ах, спасибо. Я протестирую это, если оно мне понадобится снова, а пока мы написали совершенно другую версию программного обеспечения с Qt Jambi. ;) - person Lemming; 07.11.2009

Вы проверили, что ваш метод вызывается с key как @"onOrderOut" и что ваш метод возвращает правильную анимацию?

person Colin Barrett    schedule 28.10.2008
comment
да. В реальном коде я сначала вызываю NSLog с именем действия, и действительно, запрашивается onOrderOut. Я также убедился, что анимация создается и возвращается, но все равно ее просто игнорируют. - person Lemming; 31.10.2008