iOS如何自定义转场动画
创始人
2024-12-20 01:31:21
0次

预备

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

UIViewControllerAnimatedTransitioning: 实现此协议的实例控制转场动画效果。UIViewControllerInteractiveTransitioning: 实现此协议的实例控制着利用手势过渡时的进度处理。

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

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

模态跳转(Present)

场景

self.present(vc!, animated: true) {}self.dismiss(animated: true) {}

实现步骤

  1. 设置将要 present 的 ViewController 的 transitioningDelegate 对象,此对象是实现协议 UIViewControllerTransitioningDelegate 的实例。实现 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。实现 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

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

/// UIViewControllerTransitioningDelegateoptional func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?optional func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?/// UINavigationControllerDelegateoptional func navigationController(_ navigationController: UINavigationController,          interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?

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

场景

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

实现步骤

  1. 设置 UITabbarController 的 delegate。实现 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 框架。在需要转场的类中,将 Lottie import。因为 Lottie 实现的转场实际上是 Present 的转场,所以设置将要 Present 的控制器的 transitioningDelegate。实现 UIViewControllerTransitioningDelegate 协议中的几个代理方法,返回利用转场动画 json 文件初始化的 LOTAnimationTransitionController 的实例。

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

实例

/// 第一个 VCfunc 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 }}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...