上一篇文章介绍了如何进行modal方式的页面切换

自定义的目的控制器在modal切换时完全覆盖源控制器,本篇文章介绍如何实现一个自定义的过渡效果

实现的效果描述:

    目的控制器:占据屏幕的二分之一大小,且居中,并在源控制器上覆盖着一个阴影效果,点击阴影时目的控制器返回

  • UIPresentationController

用于描述目的控制器通过modal方式切换的过渡效果

实现其子类,可以自定义出特殊的效果

实现步骤:

  1. 定义过渡效果:实现UIPresentationController子类

  2. 目的控制器,遵循过渡协议,设置过渡控制器对象

  3. 源控制器进行modal切换

UIPresentationController的属性:

@property(nonatomic, retain, readonly) UIViewController *presentedViewController   //目的控制器@property(nonatomic, retain, readonly) UIViewController*presentingViewController   //源控制器- (UIView *)presentedView  //目的view     @property(nonatomic, readonly) UIView *containerView  //源view

  • UIPresentationController的子类应重写的方法

1)init方法,可以创建其他辅助过渡效果的view

- (instancetype)initWithPresentedViewController:(UIViewController*)presentedViewController presentingViewController:(UIViewController*)presentingViewController

    如:

- (instancetype)initWithPresentedViewController:(UIViewController*)presentedViewController presentingViewController:(UIViewController*)presentingViewController {        if ( self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController] ) {        _shadowBtn = [UIButton buttonWithType:UIButtonTypeCustom];        //阴影按钮的初始状态是隐藏的        _shadowBtn.backgroundColor = [UIColor grayColor];        _shadowBtn.alpha = 0.f;    }}

2)重写presentationTransitionWillbegin方法,定义实现过渡效果

- (void)presentationTransitionWillBegin

    如:

- (void)presentationTransitionWillBegin{    [self.containerView addSubview:_shadowBtn];    [self.containerView addSubview:self.presentedView];    _shadowBtn.frame = self.containerView.bounds;    id 
 coordinate = self.presetingViewController.transitionCoordinator;    [coordinate animateAlongsideTransition:^(id
 _Nonnull context) {        _shadowBtn.alpha = 0.5;    } completion:nil];}

    使用到UIViewController的transitionCoordinator,表示过渡效果的协助器

     协助器的animateAlongsideTransition方法定义过渡期间的动画效果

3)重写presentationTransitionDidEnd方法,定义过渡效果后的清理工作。

    特别是过渡未完成时的清理动作

- (void)presentationTransitionDidEnd:(BOOL)completed
- (void)presentationTransitionDidEnd:(BOOL)completed{    if ( !completed ) {        [_shadowBtn removeFromSuperview];    }}

4)重写frameOfPresentedViewInContainerView,设置被显示视图的frame

- (CGRect)frameOfPresentedViewInContainerView
- (CGRect)frameOfPresentedViewInContainerView{    CGFloat x, y, w, h;    w = self.containerView.frame.size.width/2;    h = self.containerView.frame.size.height/2;    x = self.containerView.frame.size.width/4;    y = self.containerView.frame.size.height/4;    return CGRectMake(x, y, w, h);}

5)重写dismissTransitionWillBegin方法,设置返回的过渡效果

- (void)dismissalTransitionWillBegin
- (void)dismissalTransitionWillBegin{    id
 coordinator = self.presetingViewController.transitionCoordinator;    [coordinator animateAlongsideTransition:^(id
 _Nonull context) {        _shadowBtn.alpha = 0.01;    } completion:nil];}

6)重写dismissalTransitionDidEnd方法,执行清理动作

- (void)dismissalTransitionDidEnd:(BOOL)completed
- (void)dismissalTransitionDidEnd:(BOOL)completed{    if ( completed ) {        [_shadowView removeFromSuperview];    }}

     

  • 目的控制器设置过渡效果

目的控制器遵循代理协议

@interface AMDestViewController () 

设置代理

self.transitioningDelegate = self;

实现代理方法

- (UIPresetationController *) presentationControllerForPresentedViewController:(UIViewController*) presented presentingViewController:(UIViewController*) presenting sourceViewController:(UIViewController*) source{    return [[AMPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];}

  • 源控制器进行modal切换

iOS8.0开始支持这种自定义的过渡效果,主要要设置目的控制器的modalPresentationStyle为自定义。

这种切换方式,在iPhone和iPad上都是可用的。

AMDestViewController * vc = [[AMDestViewController alloct] init];vc.modalPresentationStyle = UIModalPresentationCustom;[self presentViewController:vc animated:YES completion:nil];