iOS 10 中的 UIVisualEffectView
UIVisualEffectView in iOS 10
我正在展示一个包含 UIVisualEffectView 的 UIViewController,如下所示:
-(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,这样当带有模糊的视图控制器出现时,模糊将 'applied' 显示它的视图控制器的内容; segue 有一个 Cross Dissolve 过渡风格。
效果符合预期。但是,在 iOS 9 中,呈现比在 iOS 10 中更流畅。在 iOS 10 中,当视图控制器出现时,它看起来像一个两步动画,而在 iOS 9 立即应用模糊。
一图胜千言,所以我上传了一段展示这种奇怪行为的视频:
UIVisualEffectView iOS 9 vs iOS 10
我的问题是:如何在 iOS 10 中呈现视图控制器,就像它在 iOS 9 中呈现的那样?
iOS 10 改变了 UIVisualEffectView
的工作方式,它打破了许多严格来说不属于 "legal" 但以前有效的用例。坚持文档,你不应该淡入 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
我正在展示一个包含 UIVisualEffectView 的 UIViewController,如下所示:
-(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,这样当带有模糊的视图控制器出现时,模糊将 'applied' 显示它的视图控制器的内容; segue 有一个 Cross Dissolve 过渡风格。
效果符合预期。但是,在 iOS 9 中,呈现比在 iOS 10 中更流畅。在 iOS 10 中,当视图控制器出现时,它看起来像一个两步动画,而在 iOS 9 立即应用模糊。
一图胜千言,所以我上传了一段展示这种奇怪行为的视频:
UIVisualEffectView iOS 9 vs iOS 10
我的问题是:如何在 iOS 10 中呈现视图控制器,就像它在 iOS 9 中呈现的那样?
iOS 10 改变了 UIVisualEffectView
的工作方式,它打破了许多严格来说不属于 "legal" 但以前有效的用例。坚持文档,你不应该淡入 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