美文网首页
iOS自定义转场动画

iOS自定义转场动画

作者: biu_iOS | 来源:发表于2018-10-18 14:42 被阅读0次

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

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

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

    @interface KKNavAnimation : NSObject <UIViewControllerAnimatedTransitioning>
    @end
    

    并在.m文件中实现

    #此方法设置转场动画的时间 
    -  (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        return 0.5f;
    }
    
    #此方法中实现自定义转场动画 根据自己的需求来
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)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<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)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自定义转场动画

          本文链接:https://www.haomeiwen.com/subject/mwajzftx.html