2016-09-24 20 views
30

przytaczam UIViewController, który zawiera UIVisualEffectView następująco:UIVisualEffectView w 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; 
    } 
} 

Jak widać, używam UIModalPresentationStyleOverFullScreen tak, że gdy pojawi się kontroler widoku z blur, rozmycie będzie być "zastosowane" do treści kontrolera widoku, który je prezentuje; styl ma styl przejściowy Cross Dissolve.

Efekt wygląda tak, jak powinien. Jednak w iOS 9 prezentacja jest płynniejsza niż w systemie iOS 10. W iOS 10, gdy pojawia się kontroler widoku, wydaje się, że jest to animacja 2-etapowa, natomiast w iOS 9 rozmycie jest natychmiast stosowane.

Obraz jest wart tysiąca słów, więc przesłał film pokazujący to dziwne zachowanie:

UIVisualEffectView iOS 9 vs iOS 10

Moje pytanie brzmi: Jak mogę przedstawić kontroler Zobacz w iOS 10, jak to jest przedstawione w iOS 9?

Odpowiedz

26

System iOS 10 zmienił sposób, w jaki działa UIVisualEffectView i złamał wiele przypadków użycia, które nie były ściśle "legalne", ale działały wcześniej. Trzymając się dokumentacji, nie powinieneś znikać w UIVisualEffectView, co dzieje się, gdy używasz UIModalTransitionStyleCrossDissolve. Wygląda na to, że jest uszkodzony na iOS 10, wraz z maskowaniem widoków efektów wizualnych i innych.

W twoim przypadku proponuję łatwą poprawkę, która również zapewni lepszy efekt niż wcześniej i jest obsługiwana zarówno w systemie iOS 9, jak i 10. Utwórz niestandardową prezentację i zamiast wygaszać widok, animuj właściwość effect od nil do efektu rozmycia. W razie potrzeby możesz przeniknąć do pozostałej części hierarchii widoków. To będzie starannie animować promień rozmycia podobny do tego, jak wygląda, gdy wyłączysz ikony ekranu głównego.

+3

Awesome! Działa świetnie. Użyłem tego samego projektu, którego użyłem do opublikowanego przeze mnie filmu, i przesłałem go do GitHub razem z twoim rozwiązaniem. Dziękuję Ci. > https://github.com/Axort/BlurTest-iOS10 – Axort

+1

Proponuję użyć animacji wiosennej i trwać 0,5. Oto, co robi tubylec. –

+0

@Axort masz szybką wersję tego? – user2722667

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

testowane zarówno iOS9 i 10. działa dobrze dla mnie

3

kodeksu poniżej rozmycie dominującej widoku kontrolera gdy ViewController prezentowane. Przetestowano na urządzeniach z systemem iOS9 i 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