iOS 自定义转场动画

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

内容简介:在开发中,无论我们使用 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 自定义转场动画》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

以奋斗者为本

以奋斗者为本

黄卫伟 / 中信出版社 / 2014-11-1 / 68.00元

《以奋斗者为本:华为公司人力资源管理纲要》传承于《华为公司基本法》,华为管理层25年人力资源管理思想精髓,5年整理,华为公司内训教材,首次大公开!作为华为公司内部培训教材,原汁原味,是继《华为基本法》之后华为的标志性著作,对国内外企业管理者&研究者具有高度的研究及借鉴价值。《以奋斗者为本:华为公司人力资源管理纲要》由华为公司首席管理科学家主编,华为高管及顾问参与编著,华为管理层25年实践,权威出品......一起来看看 《以奋斗者为本》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码