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 条评论
登录 后参与评论

相关文章

来自专栏三流程序员的挣扎

Android 动画总结(8) - Activity 转场动画

从 Android 5.0 之后,可以用 ActivityOptions 来实现,ActivityOptionsCompat 是 support v4 的兼容实...

5532
来自专栏滕先生的博客

UIGestureRecognizer  手势识别一、概念介绍二、UIView 的分类三、UIGestureRecognizer 抽象类四、UIGestureRecognizerDelegate 代理

3558
来自专栏進无尽的文章

UI篇-关于单个页面屏幕旋转要注意的问题

有时候,我们会需要在整个项目中,使某一个ViewController支持屏幕旋转,而其他的ViewController并不能自动旋转。这是一个很常见的需求,下面...

1912
来自专栏Venyo 的专栏

WinForm 为 DataGridViewCell 绑定 DataGridView

先上效果图。 ? ? 对外提供一个 public 的方法: // 正常 Type1 是 JSON 的数据集或者 BSON 的数据集 public void ...

2395
来自专栏向治洪

React Native控件之ListView

概述 ListView作为核心组件之一,主要用于高效地显示一个可以垂直滚动的变化的数据列表。经过自定义组装,我们还可以用它实现九宫格等页面效果。 在Reac...

2697
来自专栏向治洪

Android系统服务之WindowManager整理

概述 WindowManager是Android中一个重要的服务(Service )。WindowManager Service 是全局的,是唯一的。它将用户的...

19410
来自专栏一“技”之长

iOS开发UINavigation系列四——导航控制器UINavigationController

        在前面的博客中,我么你介绍了UINavigationBar,UINavigationItem和UIToolBar,UINavigationCon...

932
来自专栏QQ音乐技术团队的专栏

轻听变色之谜

轻听是一款小而美的 Android 本地音乐播放器,而它的特点之一就是拥有多彩的外衣,那么轻听是如何实现变色的呢?

3560
来自专栏滕先生的博客

UINavigationController 导航控制器概念属性方法

2866
来自专栏飞雪无情的博客

Android中为图标加上数字--用于未读短信数提醒,待更新应用数提醒等

在我们开发一些如短消息、应用商店等应用时,会考虑在短消息的图标上加上未读短信的数量,在应用商店上加上可以升级的应用数量,这样不占太大空间还能达到提示的目的。

914

扫码关注云+社区