自定义viewController的present切换动画

先上最终的效果图吧

end.gif
这是A视图控制器B视图控制器 present出来的一个效果,系统默认的present的样式是B从下往上出来,并且在B完全显示之后A是不可见的,所以要实现这种效果必须自定义样式了。

要自定义presentation风格,B需要先遵守协议UIViewControllerTransitioningDelegate、设置modalPresentationStyle和transitioningDelegate。

self.modalPresentationStyle = UIModalPresentationCustom;
self.transitioningDelegate = self;

这两句代码需要放到init方法中。

要实现示例中的效果,我们可以分为以下几个步骤:

  1. 使A的view始终可见。
  2. 自定义present的动画。
  3. 自定义dismiss的动画。
使A的view始终可见

创建UIPresentationController的子类MyPresentationController,重写方法shouldRemovePresentersView.

@implementation MyPresentationController
- (BOOL)shouldRemovePresentersView {
    return NO;
}
@end

B 中实现协议UIViewControllerTransitioningDelegate的方法

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

这样我们第一步完成,效果如图

Bvisible.gif

自定义present的动画

创建一个NSObject的子类BounceAnimationController,使其遵守协议UIViewControllerAnimatedTransitioning,并实现协议中相应的方法。

@implementation BounceAnimationController

//指明动画将执行多长时间
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.4;
}

//指明从A切入到B的过程中将执行的方法。
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    //toViewController:即B视图控制器
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    //toView:B视图控制器的view
    UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
    //containView:可以理解为它管理着所有做转场动画的视图,必须将toView加入到其中
    UIView *containView = [transitionContext containerView];

    if (containView != nil && toView != nil && toViewController != nil) {

        toView.frame = [transitionContext finalFrameForViewController:toViewController];
        [containView addSubview:toView];
        //contentView:示例中的弹框,因为我只需对弹框做动画
        UIView *contentView = [toView viewWithTag:1000];
        contentView.transform = CGAffineTransformMakeScale(0.7, 0.7);
        //以下是keyframe动画
        [UIView animateKeyframesWithDuration:[self transitionDuration:transitionContext] delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{

            [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.334 animations:^{
                contentView.transform = CGAffineTransformMakeScale(1.2, 1.2);
            }];

            [UIView addKeyframeWithRelativeStartTime:0.334 relativeDuration:0.333 animations:^{
                contentView.transform = CGAffineTransformMakeScale(0.9, 0.9);
            }];

            [UIView addKeyframeWithRelativeStartTime:0.667 relativeDuration:0.333 animations:^{
                contentView.transform = CGAffineTransformMakeScale(1.0, 1.0);
            }];

        } completion:^(BOOL finished) {
            //报告动画完成
            [transitionContext completeTransition:finished];
        }];
    }
}

@end

B中实现协议UIViewControllerTransitioningDelegate中的方法告诉代理VC在present的时候使用自定义的切换效果。

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    return [[BounceAnimationController alloc]init];
}

这样我们第二步就完成了,来看看效果:
present.gif

最后一步:自定义dismiss的动画

示例中dismiss是直接将B的view的透明度以动画的形式设置为0.创建NSObject的子类FadeOutAnimationController,使其遵守协议UIViewControllerAnimatedTransitioning,并实现协议中相应的方法。由于和自定义present动画几乎一样,所以我只将动画部分代码贴出来。

//因为是dismiss的时候是从B切换到A,所以此时fromView是B的view
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
NSTimeInterval duration = [self transitionDuration:transitionContext];
if (fromView != nil) {
   [UIView animateWithDuration:duration animations:^{
       fromView.alpha = 0;
    } completion:^(BOOL finished) {
            [transitionContext completeTransition:finished];
    }];
}

B中实现协议UIViewControllerTransitioningDelegate中的方法告诉代理VC在dismiss的时候使用自定义的切换效果。

- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    return [[FadeOutAnimationController alloc]init];
}

到这里我们的自定义viewController切换动画就完成啦。

推荐阅读:WWDC 2013 Session笔记 - iOS7中的ViewController切换
本文demo地址

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值