iOS 自定义转场动画

栏目: IOS · 发布时间: 4年前

内容简介:在开发中,无论我们使用 Push 还是 Present 推出新的 ViewController 时,系统为了提高用户体验都会为我们默认加上一些过渡动画。但是,系统默认的动画总是不能满足大家各种各样的需求的,所以系统也为我们提供了在不同场景下自定义过渡动画以及通过手势控制过渡进度的实现方案。这篇文章记录了自定义转场动画中的几种情况:首先,我们现在介绍几个在自定义转场动画时需要接触的协议:

在开发中,无论我们使用 Push 还是 Present 推出新的 ViewController 时,系统为了提高用户体验都会为我们默认加上一些过渡动画。但是,系统默认的动画总是不能满足大家各种各样的需求的,所以系统也为我们提供了在不同场景下自定义过渡动画以及通过手势控制过渡进度的实现方案。

这篇文章记录了自定义转场动画中的几种情况:

  • 模态跳转(Present)
  • 导航控制器跳转(Push)
  • UITabbarController
  • 三方框架——Lottie

效果图

iOS 自定义转场动画

预备

首先,我们现在介绍几个在自定义转场动画时需要接触的协议:

  • UIViewControllerAnimatedTransitioning:实现此协议的实例控制转场动画效果。

  • UIViewControllerInteractiveTransitioning:实现此协议的实例控制着利用手势过渡时的进度处理。

我们在定义好了实现上面两个协议的类后,只需要在需要进行转场的地方,提供对应的对象即可。

ps:下面的实例中,请大家忽略动画效果,关注实现。(其实是懒得去写太多动画了。 ‍♂️)

模态跳转(Present)

场景

self.present(vc!, animated: true) {} 
self.dismiss(animated: true) {} 
复制代码

实现步骤

  1. 设置将要 present 的 ViewController 的 transitioningDelegate 对象,此对象是实现协议 UIViewControllerTransitioningDelegate 的实例。
  2. 实现 UIViewControllerTransitioningDelegate 协议中的几个代理方法,返回实现了 UIViewControllerAnimatedTransitioning 协议的动画效果控制类。

需要实现的 UIViewControllerTransitioningDelegate 方法:

//返回用于 present 的自定义 transition 动画
optional func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
    
//返回用于 dismiss 的自定义 transition 动画
optional func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
复制代码

实例

/// 第一个 VC 中点击跳转
func presentClick(_ sender: Any) {
        let vc = self.storyboard?.instantiateViewController(withIdentifier: "PresentSecondViewController")
        
        vc?.modalPresentationStyle = .fullScreen
        
        vc?.transitioningDelegate = self
        
        self.present(vc!, animated: true) {}
}

// 第一个 VC 实现协议,返回控制转场动画效果的实例
extension PresentFirstViewController: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return NormalPresentAnimator()
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return NormalPresentAnimator()
    }
}
复制代码

导航控制器跳转(Push)

场景

self.navigationController?.pushViewController(vc!, animated: true)
self.navigationController?.popViewController(animated: true)
复制代码

实现步骤

  1. 设置导航控制器 UINavigationController 的 delegate。
  2. 实现 UINavigationControllerDelegate 协议中的代理方法,返回实现了 UIViewControllerAnimatedTransitioning 协议的动画效果控制类。

需要实现的 UINavigationControllerDelegate 方法:

optional func navigationController(_ navigationController: UINavigationController,
                              animationControllerFor operation: UINavigationController.Operation,
                              from fromVC: UIViewController,
                              to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
复制代码

实例

class PushFirstViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.navigationController?.delegate = self
    }

    @IBAction func pushClick(_ sender: Any) {
        let vc = self.storyboard?.instantiateViewController(withIdentifier: "PushSecondViewController")
        
        self.navigationController?.pushViewController(vc!, animated: true)
    }
}
extension PushFirstViewController: UINavigationControllerDelegate {
    //返回自定义过渡动画
    func navigationController(_ navigationController: UINavigationController,
                              animationControllerFor operation: UINavigationController.Operation,
                              from fromVC: UIViewController,
                              to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        if operation == .pop && fromVC is PushFirstViewController {
            return nil
        }
        
        return NormalPushAnimator()
    }
}
复制代码

UITabbarController

在前面的两个专场实现中,我们在需要转场的类中分别实现了 UIViewControllerTransitioningDelegateUINavigationControllerDelegate 方法,在这两个协议中,还有这样几个方法:

/// UIViewControllerTransitioningDelegate
optional func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?

optional func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?

/// UINavigationControllerDelegate
optional func navigationController(_ navigationController: UINavigationController,
                                       interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?
复制代码

上面这几个方法呢?其实就是我们通过利用手势转场时过渡的进度处理方法。我们需要在代理方法中返回一个实现了 UIViewControllerInteractiveTransitioning 协议的对象来对转场进度进行控制。下面的 UITabbarController 中我就实现一个利用手势控制转场的例子。 Present 及 Push/Pop 按照相同的思路实现即可。

场景

UITabbarController 在默认的状态下,切换控制器时是没有动画效果的。如果需要动画效果的话,需要我们进行自定义。

实现步骤

  1. 设置 UITabbarController 的 delegate。
  2. 实现 UITabBarControllerDelegate 协议中的代理方法,返回实现了 UIViewControllerAnimatedTransitioning 协议的动画效果控制类,以及返回实现了 UIViewControllerInteractiveTransitioning 协议的转场进度控制类。
/// 返回实现了 UIViewControllerAnimatedTransitioning 协议的实例
func tabBarController(_ tabBarController: UITabBarController,
                          animationControllerForTransitionFrom fromVC: UIViewController,
                          to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?

/// 返回实现了 UIViewControllerInteractiveTransitioning 协议的实例       
func tabBarController(_ tabBarController: UITabBarController,
                          interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?
复制代码

实例

class TabbarController: UITabBarController, UITabBarControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        self.delegate = self
}

func tabBarController(_ tabBarController: UITabBarController,
                          animationControllerForTransitionFrom fromVC: UIViewController,
                          to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        
    if self.selectedIndex == 0 {
        return TabbarAnimator(edge: .right)
    } else {
        return TabbarAnimator(edge: .left)
    }
}
    
func tabBarController(_ tabBarController: UITabBarController,
                          interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
    if self.panGesture.state == .began || self.panGesture.state == .changed {
        return TabbarInteractionTransition(pan: self.panGesture)
    } else {
        return nil
    }
}

复制代码

三方框架——Lottie

介绍

Lottie 是 Android 和 iOS 的移动库,用 bodymovin 解析 Adobe After Effects 导出为 json 的动画并在移动设备上生成矢量动画。设计师可以轻松的创建漂亮(复杂)的动画,无需 程序员 辛苦地手动去创建及调试。

场景

实现一些特殊的转场,且程序员无足够时间调试动画时。

实现步骤

  1. 在工程中导入 Lottie 框架。
  2. 在需要转场的类中,将 Lottie import。
  3. 因为 Lottie 实现的转场实际上是 Present 的转场,所以设置将要 Present 的控制器的 transitioningDelegate。
  4. 实现 UIViewControllerTransitioningDelegate 协议中的几个代理方法,返回利用转场动画 json 文件初始化的 LOTAnimationTransitionController 的实例。

ps:Lottie 转场的 LOTAnimationTransitionController 在 3.0.0 版本后被移除,所以需要使用 Lottie 做转场时,需要在导入时,指定版本号为更早的版本。我这里使用的是 2.5.3。

实例

/// 第一个 VC
func presentClick(_ sender: Any) {
    let vc = self.storyboard?.instantiateViewController(withIdentifier: "LottieSecondViewController")
    
    vc?.transitioningDelegate = self
    
    self.present(vc!, animated: true) {}
}

/// 实现 UIViewControllerTransitioningDelegate,返回  LOTAnimationTransitionController 的实例
extension LottieFirstViewController: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        
        let transitionController = LOTAnimationTransitionController(animationNamed: "Count",
                                                                    fromLayerNamed: "",
                                                                    toLayerNamed: "",
                                                                    applyAnimationTransform: false)
        return transitionController
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        let transitionController = LOTAnimationTransitionController(animationNamed: "Three",
                                                                    fromLayerNamed: "",
                                                                    toLayerNamed: "",
                                                                    applyAnimationTransform: false)
        return transitionController
    }
}

复制代码

以上所述就是小编给大家介绍的《iOS 自定义转场动画》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JAVA核心技术卷2

JAVA核心技术卷2

Cay S. Horstmann、Gary Cornell / 陈昊鹏、王浩、姚建平 / 机械工业出版社 / 2008-12 / 118.00元

《JAVA核心技术卷2:高级特征》是Java技术权威指南,全面覆盖Java技术的高级主题,包括流与文件、XML、网络、数据库编程、高级Swing、高级 AWT、JavaBean构件、安全、分布式对象、脚本、编译与注解处理等,同时涉及本地化、国际化以及Java SE 6的内容。《JAVA核心技术卷Ⅱ:高级特征》对Java技术的阐述精确到位,叙述方式深入浅出,并包含大量示例,从而帮助读者充分理解Jav......一起来看看 《JAVA核心技术卷2》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试