ViewController Transition——Modally交互动画


前言

上文介绍了非交互的Modally转场动画,初步了解到了视觉动画的效果。本文是要在其基础上添加Pan平移手势交互,完成自定义的交互动画。


一、Modally转场交互动画

交互动画为持续性动画,通过实现系统中(百分比驱动交互过渡类)UIPercentDrivenInteractiveTransition(UIViewControllerInteractiveTransitioning的子类),将视觉动画按比例过渡,达到手势动画效果。

在现实开发中的页面会出现很多的detailView,使用interactionController中present的交互手势不太符合一般用户习惯,故会很少使用到交互动画中的present

extension MainViewController:UIViewControllerTransitioningDelegate{
    //交互动画--主要是手势交互
    func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return panInteraction//实例化后,自动给DetailView添加Pan平移手势  
    }
}

PanInteraction类中添加平移手势代码如下:

class PanInteraction: UIPercentDrivenInteractiveTransition {
    
    let detailVC:DetailViewController //可以是常量,因为仅在init时被赋值一次
    var isInteractive = false
    
    init(detailVC: DetailViewController) {
        //存储属性指:一般属性,非计算属性
        //Swift规定:先给所有存储属性(包括所有父类的)赋了值之后才能使用实例化后的本对象(self)
        //Swift也规定:调用父类(super)前必须先给子类(本类)所有存储属性赋值--所以先1后2
        self.detailVC = detailVC //1.先给本类所有的存储属性赋值
        super.init() //2.再给所有父类的存储属性赋值(这句话系统默认帮我们加上的,但是是写在init最后的)
        
        //3,使用本类对象(self),调用本类的方法,获取本类的属性的值,修改父类的变量等等都在这一步完成
        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(pan:)))
        detailVC.view.addGestureRecognizer(pan)
        
    }
    
    @objc func handlePan(pan: UIPanGestureRecognizer){
        
    }
}

二、UIPercentDrivenInteractiveTransition

Pan平移手势实现

@objc func handlePan(pan: UIPanGestureRecognizer){
    //使用滑动距离和200的比,作为进度--比如:用户滑100,动画进行1/2
    //用户右滑>=200时,进度变成>=1,画面更新至完全dismiss
    //如果想用户滑多少,detail页面就消失多少的话,除数可以改成屏幕宽度-UIScreen.main.bounds.width
    let progress = pan.translation(in: pan.view).x / 200
    
    switch pan.state {
    case .began:
        detailVC.dismiss(animated: true, completion: nil)
    case .changed:
        //比如0.5的时候,动画就进行到一半的位置;手在拖动的时候,不断的更新画面
        //通过update设置转场过程动画进行的百分比,系统会根据百分比自动布局动画控件
        update(progress)
    case .cancelled , .ended:
        if progress > 0.5{
            finish()
        }else{
            cancel()
        }
    default:
        break
    }
    
}

三、transitionWasCancelled+交互状态

1.transitionWasCancelled

在实现Pan手势后,进行交互,会出现MainView的视图全部消失不见,这是因为交互动画器在完成交互动画后,要返回到DismissAnimator,且dismiss动画为视觉动画,中途不能被用户取消,则需使用transitionContext中transitionWasCancelled(仅在交互动画中有用)来判断动画是否真正的完成。

DismissAnimator(为了代码安全,在PresentAnimator上也要进行修改):

//transitionWasCancelled-如果动画被取消了,必须撤销之前对视图层级所做的修改
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)

2.非交互动画与交互动画的顺序

在设置好交互动画后,出现新的问题:点击imageView后,无法dismiss到MainView界面。这是因为设置transitioningDelegate代理后,系统会先寻找是否有交互动画,如果有,则不会将非交互动画实例化。解决方法是为其设立一个交互状态的flag,用于判断当前用户是否处于交互状态(began,changed)中,是则执行交互动画,不是则恢复非交互状态,让系统delegate去执行非交互动画中的dismiss。

修改代码如下:
PanInteraction:

class PanInteraction: UIPercentDrivenInteractiveTransition {
    
    let detailVC:DetailViewController
    var isInteractive = false
    
    init(detailVC:DetailViewController){
        self.detailVC = detailVC
        
        super.init()
        
        let pan = UIPanGestureRecognizer(target: self, action: #selector(handelePan(pan:)))
        detailVC.view.addGestureRecognizer(pan)
        
    }
    
    @objc func handelePan(pan:UIPanGestureRecognizer){
        
        let progress = pan.translation(in: pan.view).x / 200
        
        switch pan.state{
        case .began:
            isInteractive = true
            detailVC.dismiss(animated: true,completion: nil)
        case .changed:
            update(progress)
        case .cancelled , .ended:
            isInteractive = false
            if progress > 0.5{
                finish()
            }else{
                cancel()
            }
        default:
            break
        }
    }
}

MainViewController:

extension MainViewController:UIViewControllerTransitioningDelegate{
    //交互动画--主要是手势交互
    func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return panInteraction.isInteractive ? panInteraction : nil
        
        
    }
}

完成后总体效果如下:
在这里插入图片描述


总结

本次通过对交互动画认识,学习到了在interactionController中选择dismiss交互动画,跟之前的非交互动画相同,同样要返回UIViewControllerInteractiveTransitioning。与之不同的是,通过自定义的手势可将视觉动画变为播放,暂停,结束,使视觉动画变为视频播放的效果,即交互动画在视觉动画的基础上,持续性的通过用户的手势来完成动画,且交互式动画要在非交互式动画的基础上才能够实现。接下来就是对NavigationController转场动画的学习,进一步学习ViewController Transition中的知识,以便用于日后项目实例开发中。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值