iOS自定义转场动画

在UINavigationControllerDelegate代理方法中 (实现此代理方法必须遵循UINavigationControllerDelegate)

- (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{ 
}

此方法返回一个继承UIViewControllerAnimatedTransitioning协议的对象
我们只要在创建一个 遵循UIViewControllerAnimatedTransitioning协议的对象,并自定义自己的转场动画即可实现自定义转场动画

@interface KKNavAnimation : NSObject 
@end

并在.m文件中实现

#此方法设置转场动画的时间 
-  (NSTimeInterval)transitionDuration:(id)transitionContext
{
    return 0.5f;
}

#此方法中实现自定义转场动画 根据自己的需求来
- (void)animateTransition:(id)transitionContext
{
    #所有转场动画的视图都要添加到此view上 
    UIView *contentView = transitionContext.containerView;
    contentView.backgroundColor = [UIColor blackColor];
    #获取将要push到的界面 
    UIViewController* toVc = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    __block UIView *imageView = [UIView new];
    imageView.frame = self.isPush? self.origionRect : self.desRect;
    imageView.backgroundColor = self.imageView.backgroundColor;
    
    [contentView addSubview:toVc.view];
    UIView *hazylayerView = nil;
    if (!_isPush) {
        hazylayerView = [UIView new];
        NSLog(@"add layer");
        hazylayerView.backgroundColor = [UIColor yellowColor];
        [contentView addSubview:hazylayerView];
    }
    [contentView addSubview:imageView];
    

    toVc.view.alpha = 0;
    [UIView animateWithDuration:0.2 animations:^{
        toVc.view.alpha = 1;
    }];

    [UIView animateWithDuration:0.3 animations:^{
        
        imageView.frame = self.isPush? self.desRect : self.origionRect;
//        imageView.frame = self.desRect;
        NSLog(@"%@",NSStringFromCGRect(imageView.frame));
    } completion:^(BOOL finished) {
        if (self.isPush) {
            #如果是push 此处设置YES即可 如何是pop 并且要自定义侧滑返回 需要判断
            [transitionContext completeTransition:YES];
        } else {
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
            if ([transitionContext transitionWasCancelled]) {
                //手势取消了,原来隐藏的imageView要显示出来
//                fromVC.imageView.hidden = NO;
//                fromVC.titleLabel.hidden = NO;
            }else{
                //手势成功,cell的imageView也要显示出来
//                cell.imageView.hidden = NO;
//                cell.detailTextLabel.hidden = NO;
            }
        }
//        if (hazylayerView) {
//            [hazylayerView removeFromSuperview];
//        }
        [imageView removeFromSuperview];
        imageView = nil;
    }];
}

写到这里push动画已经实现了

但是会发现侧滑返回的时候 并没有执行转场动画, 设置手势需要在另一个代理方法中返回一个遵守UIViewControllerInteractiveTransitioning协议的对象

- (id)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id)animationController{
    if (!_isPush) {
        return self.interac.isInteractive == YES ? self.interac : nil;
    }
    return nil;
}

我们可以创建一个继承UIPercentDrivenInteractiveTransition的对象

@interface KKNavTransitionInteractive : UIPercentDrivenInteractiveTransition

@end

然后在.m文件中 给控制器添加手势代理方法

//给控制器的View添加相应的手势
- (void)addPanGestureForViewController:(UIViewController *)viewController{
    
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    self.viewController = viewController;
    [viewController.view addGestureRecognizer:pan];
}

- (void)handleGesture:(UIPanGestureRecognizer *)panGesture
{
    CGPoint  translation = [panGesture translationInView:panGesture.view];
    CGFloat percentComplete = 0.0;
    
    //左右滑动的百分比
    percentComplete = translation.x / (_viewController.view.frame.size.width);
    percentComplete = fabs(percentComplete);
//    NSLog(@"%f",percentComplete);
    
    switch (panGesture.state) {
        case UIGestureRecognizerStateBegan:
            [_viewController.navigationController  popViewControllerAnimated:YES];
            break;
        case UIGestureRecognizerStateChanged:{
            //手势过程中,通过updateInteractiveTransition设置转场过程动画进行的百分比,然后系统会根据百分比自动布局动画控件,不用我们控制了
            [self updateInteractiveTransition:percentComplete];
            break;
        }
        case UIGestureRecognizerStateEnded:{
            //手势完成后结束标记并且判断移动距离是否过半,过则finishInteractiveTransition完成转场操作,否者取消转场操作,转场失败
            if (percentComplete > 0.5) {
                [self finishInteractiveTransition];
            }else{
                [self cancelInteractiveTransition];
            }
            break;
        }
        default:
            break;
    }
}

大功告成
共勉

你可能感兴趣的:(iOS自定义转场动画)