iOS7自定义视图控制器过渡4-自定义手势过渡动画

24 篇文章 0 订阅

前言:之前三篇中,手势过渡动画都是直接使用事件动画的,其实我们可以使用代理方法自定义手势动画。在上一篇列子的基础上,重新定义一个手势交互动画对象。

正文:
最终效果:
这里写图片描述

由于Push和Pop时的事件动画和上篇都一样,这里着重看手势交互动画。

分析动画实现策略

—> 过渡开始前,在SecondViewController中的大图上添加一个拖拽手势。
—> 过渡开始时,对SecondViewController中的大图截图,覆盖大图位置,隐藏大图,隐藏被选中cell的imageView。
—> 移动过程中,改变SecondViewController的view的alpha值
—> 过渡完成时,对截图做动画缩小到之前被选中的cell的位置上。移除截图,SecondViewController的view的alpha值置为0,显示cell的imageView。
—> 若是取消手势,则截图回到原来的位置上后,截图移除,大图重新显示,SecondViewController的view的alpha值置为1。

手势事件:

- (void)panAction:(UIPanGestureRecognizer *)panGestureRecognizer
{
    CGPoint translation = [panGestureRecognizer translationInView:panGestureRecognizer.view];
    // 计算移动距离
    CGFloat distance = sqrtf(translation.x * translation.x + translation.y * translation.y);
    // 200是比例基数,可根据需要设置
    CGFloat progress = distance / 200;
    // 向上移动才有效
    progress = translation.y > 0 ? 0 : MIN(progress, 1.0f);

    if (panGestureRecognizer.state == UIGestureRecognizerStateBegan)
    {
        self.interactiving = YES;

        // 记录初始手指位置
        self.lastPoint = [panGestureRecognizer locationInView:panGestureRecognizer.view];

        [self.vc.navigationController popViewControllerAnimated:YES];
    }
    else if (panGestureRecognizer.state == UIGestureRecognizerStateChanged)
    {
        CGPoint currentPoint = [panGestureRecognizer locationInView:panGestureRecognizer.view];
        // 手指的位移
        self.changePoint = CGPointMake(currentPoint.x - self.lastPoint.x, currentPoint.y - self.lastPoint.y);
        self.lastPoint = currentPoint;
        [self updateInteractiveTransition:progress];
    }
    else if (panGestureRecognizer.state == UIGestureRecognizerStateCancelled)
    {
        self.interactiving = NO;
        [self cancelInteractiveTransition];
    }
    else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded)
    {
        self.interactiving = NO;
        if (progress > 0.5f) {
            [self finishInteractiveTransition];
        } else {
            [self cancelInteractiveTransition];
        }
    }
}

(1)changePoint是记录每次移动的距离,截图跟随手势移动的偏移量就是它。

过渡动画开始时的代理方法

- (void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    self.contextTransition = transitionContext;

    // 1. 获取源和目标控制器
    SecondViewController *fromVc = [self fromVc];
    FirstCollectionViewController *toVc = [self toVc];
    UIView *containerView = [self containerView];

    // 2. 截图,并初始化截图状态
    UIView *sanpShotView = [fromVc.imageInSecond snapshotViewAfterScreenUpdates:NO];
    self.sanpShotView = sanpShotView;
    sanpShotView.frame = [containerView convertRect:fromVc.imageInSecond.frame fromView:fromVc.view];
    fromVc.imageInSecond.hidden = YES;

    // 3. 初始化目标控制器的状态
    toVc.view.frame = [transitionContext finalFrameForViewController:toVc];
    FirstCellCollectionViewCell *cell = (FirstCellCollectionViewCell *)[toVc.collectionView cellForItemAtIndexPath:toVc.seletedIndexPath];
    self.selectedCell = cell;
    cell.imageInCell.hidden = YES;

    [containerView insertSubview:toVc.view belowSubview:fromVc.view];
    [containerView addSubview:sanpShotView];
}

(1)在这里对控制器的view和截图做初始状态的设置,动画不在这里做。
(2)此代理方法在[self.vc.navigationController popViewControllerAnimated:YES]之后调用。

重写 进度更新方法

- (void)updateInteractiveTransition:(CGFloat)percentComplete
{
    [super updateInteractiveTransition:percentComplete];

    // 1. 淡化当前视图控制器的view
    SecondViewController *fromVc = [self fromVc];
    fromVc.view.alpha = 1 - percentComplete;

    // 2. 随手指移动截图
    self.sanpShotView.transform = CGAffineTransformTranslate(self.sanpShotView.transform, self.changePoint.x, self.changePoint.y);

}

(1)控制器view的淡化和截图跟随效果在这里实现。由于是重写系统的方法,注意调用super。

重写 过渡完成方法

- (void)finishInteractiveTransition
{
    [super finishInteractiveTransition];

    // 截图收缩到被点击的cell的位置
    CGRect finialFrame = [self.containerView convertRect:self.selectedCell.imageInCell.frame fromView:self.selectedCell];
    [UIView animateWithDuration:self.duration
                          delay:0
         usingSpringWithDamping:0.5
          initialSpringVelocity:0.5
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         self.fromVc.view.alpha = 0.0f;
                         self.sanpShotView.frame = finialFrame;
                     } completion:^(BOOL finished) {
                         self.selectedCell.imageInCell.hidden = NO;
                         [self.sanpShotView removeFromSuperview];
                         [self.contextTransition completeTransition:YES];
                     }];
}

(1)过渡完成时需要做的事在这里完成。同时注意调用super。

重写 取消过渡方法

- (void)cancelInteractiveTransition
{
    [super cancelInteractiveTransition];

    [UIView animateWithDuration:self.duration
                          delay:0
         usingSpringWithDamping:0.5
          initialSpringVelocity:0.5
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         self.sanpShotView.transform = CGAffineTransformIdentity;
                         self.fromVc.view.alpha = 1.0f;
                     } completion:^(BOOL finished) {
                         self.fromVc.imageInSecond.hidden = NO;
                         self.selectedCell.imageInCell.hidden = NO;
                         [self.sanpShotView removeFromSuperview];
                         [self.contextTransition completeTransition:NO];
                     }];
}

(1)手势取消时,一些状态值的恢复在这里进行。注意调用super。

Demo地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值