2016-09-24 2 views
30

je présente une UIViewController qui contient un UIVisualEffectView comme suit:UIVisualEffectView dans iOS 10

-(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; 
    } 
} 

Comme vous pouvez le voir, j'utilise le UIModalPresentationStyleOverFullScreen de sorte que lorsque le contrôleur de vue avec le flou apparaît, le flou sera être «appliqué» au contenu du contrôleur de vue qui le présente; la segue a un style de transition Cross-Dissolve.

L'effet est normal. Cependant, dans iOS 9, la présentation est plus fluide que dans iOS 10. Dans iOS 10, lorsque le contrôleur de vue apparaît, cela ressemble à une animation en deux étapes, tandis que dans iOS 9, le flou est appliqué immédiatement.

Une image vaut mille mots, donc j'uploadé une vidéo montrant ce comportement étrange:

UIVisualEffectView iOS 9 vs iOS 10

Ma question est: Comment puis-je présenter le contrôleur de vue dans iOS 10 comme il est présenté dans iOS 9?

Répondre

26

iOS 10 a changé la façon dont fonctionne UIVisualEffectView, et il a cassé de nombreux cas d'utilisation qui n'étaient pas strictement "légaux", mais travaillés avant. En vous attachant à la documentation, vous ne devriez pas vous fondre dans UIVisualEffectView, ce qui arrive lorsque vous utilisez UIModalTransitionStyleCrossDissolve. Il semble maintenant cassé sur iOS 10, avec le masquage des vues d'effets visuels, et d'autres.

Dans votre cas, je suggère une solution facile qui va également créer un meilleur effet qu'auparavant, et est pris en charge sur iOS 9 et 10. Créer une présentation personnalisée et, au lieu de fondre la vue, animer la propriété effect de nil à l'effet de flou. Vous pouvez vous fondre dans le reste de votre hiérarchie de vue si nécessaire. Cela animera parfaitement le rayon de flou de la même manière que vous le feriez lorsque vous déplacerez les icônes de l'écran d'accueil.

+3

Impressionnant! Fonctionne très bien. J'ai utilisé le même projet que j'ai utilisé pour la vidéo que j'ai posté et je l'ai téléchargé sur GitHub avec votre solution. Je vous remercie. > https://github.com/Axort/BlurTest-iOS10 – Axort

+1

Je suggère d'utiliser une animation de printemps, et une durée de 0.5. C'est ce que le natif fait. –

+0

@Axort avez-vous une version rapide de cela? – user2722667

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

testé sur iOS9 et 10. fonctionne bien pour moi

3

code ci-dessous contrôleur de vue parent flou lorsqu'il est présenté ViewController. Testé à la fois sur iOS9 et sur 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