专栏首页iOSer成长记录iOS-自定义交互式转场动画

iOS-自定义交互式转场动画

自定义转场动画主要有以下步骤
  • 自定义导航栏
  • 自定义交互动画
  • 通过UIPercentDrivenInteractiveTransition协议实现交互
自定义导航栏

自定义导航栏需要遵守<UINavigationControllerDelegate>协议,该协议主要有两个协议方法:

// 该方法返回导航跳转时的动画,如果返回nil,则是系统默认的跳转动画,并且通过operation来判断当前执行push还是pop
-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
    return nil;
}
// 该方法返回自定义交互动画,只有实现该协议,才能在跳转时实现与用户交互
-(id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
    return nil;
}
自定义跳转动画

自定义跳转动画需要遵守<UIViewControllerAnimatedTransitioning>协议,该协议主要实现下面的方法:

// 该方法返回动画执行的时间,transitionContext由系统获取
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
    return 0.3;
}
// 通过该协议,获取跳转的两个VC
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    [self animateTransition:transitionContext fromVC:fromVC toVC:toVC fromView:fromVC.view toView:toVC.view];
}
// 这是模仿系统导航跳转的例子
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView{
    [[transitionContext containerView] addSubview:toView];
    if (_isPush) {
        [[transitionContext containerView] bringSubviewToFront:toView];
        toView.transform = CGAffineTransformMakeTranslation(-toView.bounds.size.width, 0);
    }
    else{
        [[transitionContext containerView] bringSubviewToFront:fromView];
    }
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        if (_isPush) {
            toView.transform = CGAffineTransformIdentity;
        }
        else{
            fromView.transform = CGAffineTransformMakeTranslation(-fromView.bounds.size.width, 0);
        }
    } completion:^(BOOL finished) {
        transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}
实现交互

自定义一个类,继承自UIPercentDrivenInteractiveTransition,它遵守<UIViewControllerInteractiveTransitioning>协议,我们可以告诉它当前转场动画进行的百分比,它再来更新动画的进度。转场动画进行的百分比可以通过手势来计算

// 在view上加入pan手势
UIPanGestureRecognizer *gesture = objc_getAssociatedObject(self.interactiveVC.view, (__bridge const void *)(kpanGestureKey));
    if (gesture) {
        [self.interactiveVC.view removeGestureRecognizer:gesture];
    }
    gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    [self.interactiveVC.view addGestureRecognizer:gesture];
    objc_setAssociatedObject(self.interactiveVC.view, (__bridge const void *)(kpanGestureKey), gesture,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// 当pan手势移动,通过移动的距离来计算当前跳转动画需要完成的百分比,当手势结束时,判断动画完成的百分比。如果>50%,finishInteractiveTransition完成跳转动画;如果<50%,cancelInteractiveTransition取消动画,返回原样
case UIGestureRecognizerStateChanged:
        CGFloat fraction = point.x / [[UIScreen mainScreen] bounds].size.width;
        fraction = fminf(fmaxf(fraction, 0.0), 1.0);
        self.shouldComplete = (fraction > 0.5);
        [self updateInteractiveTransition:fraction];
    break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
        self.interactioning = NO;
        if (!self.shouldComplete || pan.state == UIGestureRecognizerStateCancelled) {
            [self cancelInteractiveTransition];
        }
        else {
            [self finishInteractiveTransition];
        }
    break;
最后附上Demo的地址https://github.com/cdcyd/CommonControlsCollection

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • iOS-可交互滑动的TabBarController

    用户2215591
  • AlamofireImage 源码阅读

    用户2215591
  • iOS-AVFoundation自定义相机详解

    用户2215591
  • 使用c#连接sqlserver

    连接数据库是一个常见的操作,现在主流的关系数据库主要是sqlserver,mysql,Oracle,今天来聊一聊使用c#如何连接sqlserver。

    HUBU生信
  • Java 代码界 3% 的王者?看我是如何解错这 5 道题的

    但遗憾的是,凭借 8 年的 Java 开发经验,我发现这五道题自己全解错了!惨痛的教训再次证明,我是那被秒杀的 97% 的工程师之一。

    JAVA葵花宝典
  • Swift学习笔记(一)

    Originalee
  • 谈谈 JavaScript 中的 TDZ

    本来过年期间想写这个的,不过要准备些东西,一直没抽出时间,刚好今天有点空闲。上个月阮一峰阮老师在微博上发布了这样一条信息 于是评论区炸开了锅,很多人留言指出,这...

    Bob.Chen
  • OpenFlow的伴侣协议:OF-CONFIG

    1 简介 在OpenFlow协议的规范中,控制器需要和配置好的交换机进行通信。而交换机在正常工作之前需要对其特性以及资源进行配置,才能正常工作。而这些配置超出了...

    SDNLAB
  • 混合云的备忘清单

    虽然越来越多的企业将其业务工作负载地转移到云端,但监管障碍、安全问题、对遗留应用程序的依赖、异常数据集或工作流等某些情况已经成为组织将业务迁移到公共云的障碍。

    静一
  • akka-typed(7) - cluster:sharding, 集群分片

    在使用akka-typed的过程中发现有很多地方都简化了不少,变得更方便了,包括:Supervision,只要用Behaviors.supervise()把...

    用户1150956

扫码关注云+社区

领取腾讯云代金券