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, чтобы при появлении контроллера представления с размытием размытие «применялось» к содержимому контроллера представления, который его представляет; переход имеет стиль перехода Cross Dissolve.

Эффект выглядит ожидаемым. Однако в iOS 9 представление более плавное, чем в iOS 10. В iOS 10, когда появляется контроллер представления, это выглядит как двухэтапная анимация, тогда как в iOS 9 размытие применяется немедленно.

Картинка стоит тысячи слов, поэтому я загрузил видео, демонстрирующее это странное поведение:

UIVisualEffectView iOS 9 против iOS 10

Мой вопрос: как представить контроллер представления в iOS 10 так, как он представлен в iOS 9?


person Axort    schedule 24.09.2016    source источник


Ответы (3)


iOS 10 изменила способ UIVisualEffectView работы и нарушила многие варианты использования, которые, строго говоря, не были «законными», но работали раньше. Придерживаясь документации, вы не должны исчезать с UIVisualEffectView, что происходит, когда вы используете UIModalTransitionStyleCrossDissolve. Кажется, что теперь это не работает в iOS 10, вместе с маскированием визуальных эффектов и другими.

В вашем случае я бы предложил простое исправление, которое также создаст лучший эффект, чем раньше, и поддерживается как в iOS 9, так и в 10. Создайте настраиваемую презентацию и вместо постепенного увеличения изображения анимируйте свойство effect с nil на эффект размытия. При необходимости вы можете постепенно увеличивать остальную часть иерархии представлений. Это аккуратно анимирует радиус размытия, аналогично тому, как он выглядит, когда вы опускаете значки на главном экране.

person Leo Natan    schedule 26.09.2016
comment
Потрясающий! Работает отлично. Я использовал тот же проект, что и для размещенного мною видео, и загрузил его на GitHub с вашим решением. Спасибо. ›github.com/Axort/BlurTest-iOS10 - person Axort; 27.09.2016
comment
Я предлагаю использовать весеннюю анимацию и длительностью 0,5. Это то, что делает родной. - person Leo Natan; 27.09.2016
comment
@Axort, у вас есть быстрая версия? - person user2722667; 20.10.2016
comment
@ user2722667 На данный момент нет): - person Axort; 20.10.2016
comment
Спасибо за это. Он работает так, как рекламируется. Просто обратите внимание, что сначала вы должны установить для свойства эффекта вашего визуального эффекта значение nil. Затем вы анимируете свой целевой эффект. (например, свет). И вы не можете установить альфа ни для представления визуальных эффектов, ни для любого супервизора. (Это вроде как работает в iOS 9, но не работает в iOS 10.) Еще один прекрасный API, предоставленный вам Apple. Все, что я могу сказать, это спасибо за Stack Overflow и его участников ... - person Womble; 17.11.2016
comment
@Axort спасибо за ваше решение github, отлично работает !! - person sudoExclaimationExclaimation; 27.11.2016

    UIView.animate(withDuration: 0.5) {
        self.effectView.effect = UIBlurEffect(style: .light)
    }

Проверено как на iOS9, так и на 10. У меня работает нормально.

person Allen Zhao    schedule 27.09.2016

Код ниже размывает родительский контроллер представления при представлении 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
person Artem Illarionov    schedule 15.12.2016