NSFindow setFrame:display:animate: запускаться одновременно с другими анимациями
Я использую NSWindow без полей для создания слайд-меню, которое вы можете найти во многих приложениях IOS. В настоящее время я использую setFrame:display:animate: с двумя предопределенными ритами для создания скользящего эффекта, а также у меня есть анимация, которая затеняет фон основного окна, который в данный момент запускается после того, как окно завершило анимацию.
Я бы очень хотел запустить обе эти анимации одновременно. Однако setFrame: display: animate, похоже, блокирует весь другой код до его завершения.
Есть ли способ переопределить эту функцию setFrame: display: animate? Или кто-нибудь может порекомендовать обходной путь?
У меня есть методы работы, которые запускают [[self animator]setFrame:display:], но я бы предпочел использовать setFrame: display: animate, потому что он широко представлен в моем текущем коде и его легко настроить на длительность.
Некоторый код:
//Currently used to animate the window
-(void)showPopWindow{
[self selectAnimationTimeFor:NCpOpen];
[self setFrame:_initialRect display:YES];
[self makeKeyAndOrderFront:NSApp];
[self setFrame:_finalRect display:YES animate:YES];
}
И это другая анимация, которая у меня есть, которая в настоящий момент запускается после завершения setFrame (обратите внимание, что она выполняется на уровне NSView).
//...
[layer setBackgroundColor:CGColorCreateGenericRGB(0, 0, 0, 0.5)];
CABasicAnimation *fadeInBackground = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeBackground.duration = [self openAnimationResizeTime];
fadeBackground.fromValue = [NSNumber numberWithFloat:0.0f];
fadeBackground.toValue = [NSNumber numberWithFloat:1.0f];
[layer addAnimation:fadeInBackground forKey:@"opacity"];
2 ответа
Решил проблему, используя NSAnimationContext вместе с [[self animator]setAlphaValue:], что позволяет мне запускать одновременные анимации и затем выполнять блок по завершении.
Документация:
Рабочий код:
// To avoid a strong reference cycle to self in block
__weak typeof(self)weakSelf = self;
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setDuration: myDuration];
[[weakSelf animator] setFrame:_initialRect display:YES];
// ... other animations
} completionHandler:^{
NSLog(@"done");
[[weakSelf overCastView] removeFromSuperview];
weakSelf.overCastView = nil;
}];
Следующее сработало для меня (с благодарностью за этот ответ). Я думаю, что это более "правильное" решение из-за явного NSAnimationNonblocking
:
NSRect myNewFrame = NSMakeRect(0, 0, 123, 456);
NSDictionary* windowResize = [NSDictionary dictionaryWithObjectsAndKeys: window, NSViewAnimationTargetKey, [NSValue valueWithRect: myNewFrame], NSViewAnimationEndFrameKey, nil];
NSArray* animations = [NSArray arrayWithObjects:windowResize, nil];
NSViewAnimation* animation = [[NSViewAnimation alloc] initWithViewAnimations: animations];
[animation setAnimationBlockingMode: NSAnimationNonblocking];
[animation setAnimationCurve: NSAnimationEaseIn];
[animation setDuration: 0.4];
[animation startAnimation];