UIVisualEffectView en iOS 10
objective-c ios10 (3)
El código a continuación desdibuja el controlador de vista principal cuando se presenta ViewController. Probado tanto en iOS9 como en 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
Estoy presentando un UIViewController que contiene un UIVisualEffectView de la siguiente manera:
-(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;
}
}
Como puede ver, estoy usando UIModalPresentationStyleOverFullScreen para que cuando aparezca el controlador de vista con desenfoque, el desenfoque se ''aplique'' al contenido del controlador de vista que lo presenta; el segue tiene un estilo de transición de Disolución cruzada.
El efecto se ve como se esperaba. Sin embargo, en iOS 9 la presentación es más suave que en iOS 10. En iOS 10 cuando aparece el controlador de vista parece una animación de 2 pasos, mientras que en iOS 9 el desenfoque se aplica de inmediato.
Una imagen vale más que mil palabras, así que subí un video que muestra este extraño comportamiento:
UIVisualEffectView iOS 9 vs iOS 10
Mi pregunta es: ¿cómo puedo presentar el controlador de vista en iOS 10 ya que se presenta en iOS 9?
iOS 10 ha cambiado la forma en que UIVisualEffectView
funciona, y ha roto muchos casos de uso que no eran estrictamente "legales", pero que funcionaban antes. Al apegarse a la documentación, no debería estar desapareciendo en UIVisualEffectView
, que es lo que sucede cuando utiliza UIModalTransitionStyleCrossDissolve
. Ahora parece estar roto en iOS 10, junto con el enmascaramiento de vistas de efectos visuales, y otros.
En su caso, sugeriría una solución fácil que también creará un efecto mejor que antes, y se admite tanto en iOS 9 como en 10. Cree una presentación personalizada y, en lugar de atenuar la vista, anime la propiedad del effect
de nil
a efecto de desenfoque. Puede desaparecer en el resto de la jerarquía de vistas si es necesario. Esto animará nítidamente el radio de desenfoque similar a como se ve cuando tira de los iconos de la pantalla de inicio hacia abajo.
UIView.animate(withDuration: 0.5) {
self.effectView.effect = UIBlurEffect(style: .light)
}
Probado en iOS9 y 10. Funciona bien para mí