Выборочное переопределение неявных анимаций CALayer - PullRequest
3 голосов
/ 08 апреля 2011

У меня есть подкласс CALayer, который ограничен шириной родительского слоя, но имеет фиксированную высоту.Я хочу, чтобы неявная анимация была отключена для изменения размера окна, но включена всякий раз, когда я устанавливаю высоту слоя.

Чтобы отключить анимацию при изменении размера окна, я устанавливаю действия слоев на

NSMutableDictionary *actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"bounds", [NSNull null], @"position", nil];

и это похоже на работу.Затем я переопределил actionForKey: метод в моем подклассе слоя

- (id<CAAction>)actionForKey:(NSString *)event
{
    if ([event isEqualToString:@"frame.size.height"]) {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"frame.size.height"];
        [animation setDuration:0.5f];
        return animation;
    }
    return nil;
}

, но затем, когда я изменяю высоту моего слоя с помощью

[layer setValue:[NSNumber numberForFloat:50.0] forKey:@"frame.size.height"];

, высота изменяется, но не анимируется.Я вижу actionForKey: метод, вызываемый с frame.size.height, но независимо от того, что я возвращаю, он никогда не анимируется.Высота анимируется правильно, если я не установил действия или у меня нет метода actionForKey:, но тогда размеры окна также анимируются, чего я не хочу.

Кроме того, возможно, я неправильно понимаю,но я думал, что возврат nil из actionForKey: заставит запускать анимации по умолчанию, но кажется, что даже наличие метода останавливает все неявные анимации (установлен ли словарь действий или нет).

Что мне здесь не хватает, буду благодарен за любые указатели.

Ответы [ 2 ]

3 голосов
/ 08 апреля 2011

Ваш подкласс будет вызывать actionForKey: для каждого ключа, поэтому если вы вернете nil, для этого ключа не будет действия. Если вы хотите использовать анимацию по умолчанию, вы должны вернуть либо [super actionForKey:event], либо [CALayer defaultActionForKey:event].

Слой frame рассчитывается по его bounds и position, поэтому, если для этих двоих нет анимации, анимация для frame. *

невозможна.

Что вы хотите сделать, это:

[CATransaction setValue:kCFBooleanTrue
                 forKey:kCATransactionDisableActions]

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


*: На самом деле, в документах говорится:

Примечание. Свойство frame напрямую не анимируется. Вместо этого вы должны анимировать соответствующую комбинацию свойств bounds, anchorPoint и position для достижения желаемого результата.

2 голосов
/ 25 июня 2013

Есть, как говорится .. несколько способов сделать скин для этого кота ... Я считаю, что одним из самых простых будет ... путем установки некоторых записей в словаре "Действия" слоя ..

CALayer *stopAnimatingLikeThat = CALayer.new;
stopAnimatingLikeThat.actions  =
  @{ @"position":NSNull.null, @"bounds":NSNull.null };

Это остановит раздражающие неявные анимации «застрял в меде» на изменениях границ и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...