NSView CALayer Opacity Madness - PullRequest
       6

NSView CALayer Opacity Madness

2 голосов
/ 24 июля 2011

Кажется, что свойства слоя моего NSView иногда не редактируются / неправильно. В приведенном ниже коде анимация работает отлично, и все выглядит нормально. Выходные данные из NSlogs всегда:

anim over opacity = 1.00000
first opacity = 0.50000
current opacity = 0.00000
updated opacity = 0.00000

Первые два журнала выглядят правильно, поэтому, даже когда анимация остановилась, слой работает нормально. Однако через некоторое время, когда я проверяю непрозрачность, она волшебным образом превращается в 0. Еще хуже, когда я устанавливаю непрозрачность слоя на 1 и проверяю его сразу после этого, он все еще равен 0. Как это возможно?

Я дурачился с setneedsdisplay в слое и setneedsdisplay: ДА в nsview и это не помогло Любые предложения с благодарностью.

- (void) someSetupAnimationMethod {
        aLayer = [CALayer layer];
        [theView setWantsLayer:YES];
        [theView setLayer:aLayer];

        [aLayer setOpacity:0.0];
        CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"];
        opacity.byValue = [NSNumber numberWithFloat:1.0];
        opacity.duration = 0.3;
        opacity.delegate = self;
        opacity.fillMode = kCAFillModeForwards;
        opacity.removedOnCompletion = NO;
        [opacity setValue:@"opacity done" forKey:@"animation"];
        [aLayer addAnimation:opacity forKey:nil];
    }

    - (void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        if([[anim valueForKey:@"animation"] isEqualToString:@"opacity done"]) {
           NSLog(@"anim over opacity = %f", aLayer.opacity);
           aLayer.opacity = 0.5;
           [aLyaer removeAllAnimations];
           NSLog(@"first opacity = %f", aLayer.opacity);
        }
    }

    - (void) someLaterMethod {
        NSLog(@"current opacity = %f", aLayer.opacity);
        aLayer.opacity = 1.0;
        NSLog(@"updated opacity = %f", aLayer.opacity);
    }

1 Ответ

8 голосов
/ 24 июля 2011

Вы нарушаете фундаментальное правило CALayer / NSView, создавая представление на основе слоя и затем пытаясь напрямую манипулировать слоем.

aLayer = [CALayer layer];
[theView setWantsLayer:YES];
[theView setLayer:aLayer];

Когда вы говорите представлению использоватьСлой перед вызовом setLayer: вид становится «слоистым» - он просто использует слой в качестве буфера, и все рисование, которое вы хотите сделать, должно выполняться обычными drawRect: и связанными методами.Вам не разрешено непосредственно касаться слоя.Если вы измените порядок этих вызовов:

[theView setLayer:aLayer];
[theView setWantsLayer:YES];

Теперь у вас есть представление «Слой-хостинг», что означает, что представление просто обеспечивает пространство на экране для слоя, в который нужно рисовать.В этом случае вы рисуете прямо в слой.Поскольку содержимое слоя становится содержимым представления, вы не можете добавлять подпредставления или использовать механизмы рисования представления.

Это упоминается в документации -[NSView setWantsLayer:];Я также нашел старую ветку какао-разработчика , которая довольно хорошо это объясняет.

Я не уверен, что это решит вашу проблему, но, насколько я вижу, вы делаете все остальное правильно, например, устанавливаете режим заполнения и обновляете значение после завершения анимации.

...