欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-25 09:09:42
...
自定义转场动画主要有以下步骤
  • 自定义导航栏
  • 自定义交互动画
  • 通过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