iOS开发_具有毛玻璃效果的modal控制器

1、使用

  • 新建控制器时继承 GC_Blur_Controller,然后按照正常的modal控制器使用即可。
  • 1.1 继承

#import "GC_Blur_Controller.h"

@interface Presented_Controller : GC_Blur_Controller

@end
  • 1.2 使用

Presented_Controller *pvc = [[Presented_Controller alloc] init];
pvc.blurStyle = UIBlurEffectStyleLight;
[self presentViewController:pvc animated:YES completion:nil];

2、实现代码

  • 2.1 GC_Blur_Controller.h

#import <UIKit/UIKit.h>

@interface GC_Blur_Controller : UIViewController

@property(nonatomic, assign) UIBlurEffectStyle blurStyle;

@end
  • 2.2 GC_Blur_Controller.m

#import "GC_Blur_Controller.h"

@interface GC_Blur_Presenter : NSObject <UIViewControllerTransitioningDelegate>

@property(nonatomic, assign) UIBlurEffectStyle blurStyle;

@end

@class GC_Blur_Presentation_Controller;
@protocol GC_Blur_Presentation_Controller_Delegate <NSObject>

- (void)presentationControllerDidDismissed:(GC_Blur_Presentation_Controller *)controller;

@end

@interface GC_Blur_Presentation_Controller : UIPresentationController

@property(nonatomic, assign) UIBlurEffectStyle blurStyle;

@property(nonatomic, weak) id<GC_Blur_Presentation_Controller_Delegate> gc_delegate;

- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController
                       presentingViewController:(UIViewController *)presentingViewController
                                          style:(UIBlurEffectStyle)style;

@end

@interface GC_Blur_Transitioning : NSObject <UIViewControllerAnimatedTransitioning>

@property(nonatomic, assign) BOOL isPresentation;

@end

@interface GC_Blur_Controller ()

@property(nonatomic, strong) GC_Blur_Presenter *presenter;

@end

@implementation GC_Blur_Controller

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self vv_commonSetup];
    }
    return self;
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        [self vv_commonSetup];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor clearColor];
}

- (void)vv_commonSetup {
    self.modalPresentationStyle = UIModalPresentationCustom;
    
    _presenter = [[GC_Blur_Presenter alloc] init];
    _blurStyle = UIBlurEffectStyleDark;
    _presenter.blurStyle = _blurStyle;
    
    self.transitioningDelegate = _presenter;
}

- (void)setBlurStyle:(UIBlurEffectStyle)blurStyle {
    if (blurStyle != _blurStyle) {
        _blurStyle = blurStyle;
        _presenter.blurStyle = blurStyle;
    }
}

@end

@interface GC_Blur_Presenter () <GC_Blur_Presentation_Controller_Delegate>

@property(nonatomic, strong) GC_Blur_Presentation_Controller *animationController;

@end

@implementation GC_Blur_Presenter

- (instancetype)init {
    self = [super init];
    if (self) {
        _blurStyle = UIBlurEffectStyleDark;
    }
    return self;
}

- (GC_Blur_Presentation_Controller *)presentationControllerForPresentedViewController:(UIViewController *)presented
                                                           presentingViewController:(UIViewController *)presenting
                                                               sourceViewController:(UIViewController *)source {
    if (!self.animationController) {
        self.animationController = [[GC_Blur_Presentation_Controller alloc] initWithPresentedViewController:presented presentingViewController:presenting style:self.blurStyle];
        self.animationController.gc_delegate = self;
    }
    return self.animationController;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
                                                                 presentingController:(UIViewController *)presenting
                                                                     sourceController:(UIViewController *)source {
    
    GC_Blur_Transitioning *transition = [[GC_Blur_Transitioning alloc] init];
    transition.isPresentation = YES;
    return transition;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    
    GC_Blur_Transitioning *transition = [[GC_Blur_Transitioning alloc] init];
    transition.isPresentation = NO;
    return transition;
}

- (void)setBlurStyle:(UIBlurEffectStyle)blurStyle {
    if (_blurStyle != blurStyle) {
        _blurStyle = blurStyle;
        self.animationController.blurStyle = blurStyle;
    }
}

- (void)presentationControllerDidDismissed:(GC_Blur_Presentation_Controller *)controller {
    self.animationController = nil;
}

@end

@interface GC_Blur_Presentation_Controller ()

@property(nonatomic, strong) UIView *effectContainerView;

@property(nonatomic, strong) UIVisualEffectView *dimmingView;

@end

@implementation GC_Blur_Presentation_Controller

- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController style:(UIBlurEffectStyle)style {
    self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController];
    if (self) {
        UIBlurEffect *effect = [UIBlurEffect effectWithStyle:style];
        _dimmingView = [[UIVisualEffectView alloc] initWithEffect:effect];
        _blurStyle = style;
        _effectContainerView = [[UIView alloc] init];
        _effectContainerView.alpha = 0.0;
    }
    return self;
}

- (void)presentationTransitionWillBegin {
    self.effectContainerView.frame = self.containerView.bounds;
    self.dimmingView.frame = self.containerView.bounds;

    [self.effectContainerView insertSubview:self.dimmingView atIndex:0];
    [self.containerView insertSubview:self.effectContainerView atIndex:0];
    
    self.effectContainerView.alpha = 0.0;
    
    id <UIViewControllerTransitionCoordinator> coordinator = [self.presentedViewController transitionCoordinator];
    if (coordinator) {
        [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
            self.effectContainerView.alpha = 1.0;
        } completion:nil];
    }
    else {
        self.effectContainerView.alpha = 1.0;
    }
}

- (void)dismissalTransitionWillBegin {
    id <UIViewControllerTransitionCoordinator> coordinator = [self.presentedViewController transitionCoordinator];
    if (coordinator) {
        [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
            self.effectContainerView.alpha = 0.0;
        } completion:nil];
    }
    else {
        self.effectContainerView.alpha = 0.0;
    }
}

- (void)dismissalTransitionDidEnd:(BOOL)completed {
    if (completed) {
        if (self.gc_delegate && [self.gc_delegate respondsToSelector:@selector(presentationControllerDidDismissed:)]) {
            [self.gc_delegate presentationControllerDidDismissed:self];
        }
    }
}

- (void)containerViewWillLayoutSubviews {
    self.effectContainerView.frame = self.containerView.bounds;
    self.dimmingView.frame = self.containerView.bounds;
    self.presentedView.frame = self.containerView.bounds;
}

- (BOOL)shouldPresentInFullscreen {
    return YES;
}

- (UIModalPresentationStyle)adaptivePresentationStyle {
    return UIModalPresentationCustom;
}

- (void)setBlurStyle:(UIBlurEffectStyle)blurStyle {
    if (blurStyle != _blurStyle) {
        _blurStyle = blurStyle;
        
        UIView *previousDimmingView = _dimmingView;
        
        UIBlurEffect *effect = [UIBlurEffect effectWithStyle:blurStyle];
        self.dimmingView = [[UIVisualEffectView alloc] initWithEffect:effect];
        NSArray *subviews = [self.effectContainerView subviews];
        for (UIView *view in subviews) {
            if (view == previousDimmingView) {
                self.dimmingView.frame = previousDimmingView.frame;
                [self.effectContainerView insertSubview:self.dimmingView aboveSubview:previousDimmingView];
                [previousDimmingView removeFromSuperview];
            }
        }
    }
}

@end

@implementation GC_Blur_Transitioning

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
    return 0.5;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
    UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
    
    UIView *containerView = [transitionContext containerView];
    if (self.isPresentation) {
        [containerView addSubview:toView];
    }
    
    UIViewController *animatingViewController = self.isPresentation ? toViewController : fromViewController;
    UIView *animatingView = self.isPresentation ? toView : fromView;
    
    CGRect onScreenFrame = [transitionContext finalFrameForViewController:animatingViewController];
    CGRect offScreenFrame = CGRectOffset(onScreenFrame, 0, onScreenFrame.size.height);
    
    CGRect initialFrame = self.isPresentation ? offScreenFrame : onScreenFrame;
    CGRect finalFrame = self.isPresentation ? onScreenFrame : offScreenFrame;
    animatingView.frame = initialFrame;
    
    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 usingSpringWithDamping:300.0 initialSpringVelocity:5.0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionBeginFromCurrentState animations:^{
        animatingView.frame = finalFrame;
    } completion:^(BOOL finished) {
        if (!self.isPresentation) {
            [fromView removeFromSuperview];
        }
        [transitionContext completeTransition:YES];
    }];
}

@end
posted @ 2023-01-06 10:57  CH520  阅读(36)  评论(0编辑  收藏  举报