UIVisualEffectView в iOS 10
Я представляю UIViewController, который содержит UIVisualEffectView следующим образом:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:@"segueBlur" sender:nil];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:@"segueBlur"]) {
((UIViewController *)segue.destinationViewController).providesPresentationContextTransitionStyle = YES;
((UIViewController *)segue.destinationViewController).definesPresentationContext = YES;
((UIViewController *)segue.destinationViewController).modalPresentationStyle = UIModalPresentationOverFullScreen;
}
}
Как вы можете видеть, я использую UIModalPresentationStyleOverFullScreen, чтобы при появлении контроллера представления с размытием размытие было "применено" к содержимому контроллера представления, который его представляет; у перехода есть переходный стиль перекрестного растворения.
Эффект выглядит как и ожидалось. Однако в iOS 9 презентация более плавная, чем в iOS 10. В iOS 10, когда появляется контроллер представления, это выглядит как двухэтапная анимация, в то время как в iOS 9 размытие применяется немедленно.
Картинка стоит тысячи слов, поэтому я загрузил видео, показывающее это странное поведение:
UIVisualEffectView iOS 9 против iOS 10
Мой вопрос: как я могу представить контроллер представления в iOS 10, как он представлен в iOS 9?
3 ответа
iOS 10 изменил способ UIVisualEffectView
работает, и это сломало много случаев использования, которые не были строго говоря "законными", но работали раньше. Придерживаясь документации, вы не должны исчезать в UIVisualEffectView
, что происходит, когда вы используете UIModalTransitionStyleCrossDissolve
, Похоже, что теперь не работает на iOS 10, наряду с маскировкой представлений о визуальных эффектах и другими.
В вашем случае, я бы предложил простое исправление, которое также создаст лучший эффект, чем раньше, и поддерживается как в iOS 9, так и в 10. Создайте пользовательскую презентацию и вместо того, чтобы скрыть вид, анимируйте effect
собственность от nil
к эффекту размытия. При необходимости вы можете исчезнуть в остальной части иерархии представлений. Это позволит аккуратно анимировать радиус размытия, аналогично тому, как он выглядит при перетаскивании значков на главном экране.
UIView.animate(withDuration: 0.5) {
self.effectView.effect = UIBlurEffect(style: .light)
}
Протестировано на iOS9 и 10. У меня отлично работает
Код ниже размывает родительский контроллер представления, когда представлен ViewController. Протестировано на iOS9 и 10.
@interface ViewController () <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>
@property (nonatomic) UIVisualEffectView *blurView;
@end
@implementation ViewController
- (instancetype)init
{
self = [super init];
if (!self)
return nil;
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.transitioningDelegate = self;
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
self.blurView = [UIVisualEffectView new];
[self.view addSubview:self.blurView];
self.blurView.frame = self.view.bounds;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
return self;
}
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.3;
}
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIView *container = [transitionContext containerView];
[container addSubview:self.view];
self.blurView.effect = nil;
[UIView animateWithDuration:0.3 animations:^{
self.blurView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
} completion:^(BOOL finished) {
[transitionContext completeTransition:finished];
}];
}
@end