自定義TabBar動畫效果 - 頁面轉場(Swift)

weixin_33807284發表於2019-02-24

前言:之前寫過一篇自定義TabBar動畫效果的部落格OC版本,本篇換成Swift來實現動畫。思路大致相同,有需要可以去上篇部落格中檢視具體的邏輯本篇主要分享一下在Swift中核心程式碼和與OC中區別。

分三步:

1:初始化:

  • 初始化TabBar控制器

  • 遵守UITabBarControllerDelegate代理協議,實現代理方法

2:點選動畫:

核心程式碼

在代理方法tabBarController - didSelect viewController中找到對應選中的tabBarButton並對其做核心動畫

核心程式碼
/// 點選動畫
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
   
   tabBarButtonClick(tabBarButton: getTabBarButton())
   
}

private func getTabBarButton() -> UIControl {

   var tabBarButtons = Array<UIView>()
   for tabBarButton in tabBar.subviews {
       if (tabBarButton.isKind(of:NSClassFromString("UITabBarButton")!)){
           tabBarButtons.append(tabBarButton)
       }
   }
   return tabBarButtons[selectedIndex] as! UIControl
}
    
private func tabBarButtonClick(tabBarButton : UIControl) {
   
   for imageView in tabBarButton.subviews {
       if (imageView.isKind(of: NSClassFromString("UITabBarSwappableImageView")!)){
           let animation = CAKeyframeAnimation()
           animation.keyPath = "transform.scale"
           animation.duration = 0.3
           animation.calculationMode = CAAnimationCalculationMode.cubicPaced
           animation.values = [1.0,1.1,0.9,1.0]
           imageView.layer.add(animation, forKey: nil)
       }
   }
}
    

3:滑動動畫:

在代理方法tabBarController - animationControllerForTransitionFrom代理方法中做滑動動畫。

  • 這裡可以建立一個類封裝tabBarVc的滑動動畫,類似如下:
/// 滑動動畫
func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
   
   return DCSlideBarAnimation() //滑動動畫
}

在類DCSlideBarAnimation中去實現具體滑動動畫。

❗️DCSlideBarAnimation類中與OC的不同點:期初在設計OC滑動類的時候我設計一個UIRectEdge屬性來告訴類我當前選中的控制器Vc和選中前控制器Vc的一個方向偏移作為滑動動畫的dx。
❗️在swift中,我取消了這個屬性,從而在類的內部去去通過獲取當前TabVc的viewControllers的index來比較偏移方向。
相比較更建議採用第二種方法,在上傳的程式碼中我沒更改OC原來思路,可以檢視原始碼進行對比。
核心程式碼
// MARK: - 代理方法
extension DCSlideBarAnimation : UIViewControllerAnimatedTransitioning{
    
    /// 設定時間間隔
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
       return 0.15
    }
        
    /// 處理轉場
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
       
       guard let fromeVc = transitionContext.viewController(forKey: .from),
             let toVc = transitionContext.viewController(forKey: .to) else { return }
       
        
       guard let tabVc = UIApplication.shared.keyWindow?.rootViewController as? UITabBarController,
             let fromeIndex = tabVc.viewControllers?.index(where: { $0 == fromeVc}),
             let toIndex = tabVc.viewControllers?.index(where: { $0 == toVc}) else { return }
       
       guard let formView = transitionContext.view(forKey: .from),
             let toView = transitionContext.view(forKey: .to) else { return }
       
       let fromFrame : CGRect = formView.frame
       let toFrame : CGRect = toView.frame
    
      
       var offSet : CGVector?
       if toIndex > fromeIndex {
           offSet = CGVector(dx: -1, dy: 0)
       }else{
           offSet = CGVector(dx: 1, dy: 0)
       }
    
       guard let animOffSet = offSet else { return }
       formView.frame = fromFrame
    
       let ofDx : CGFloat = animOffSet.dx
       let ofDy : CGFloat = animOffSet.dy
       toView.frame = CGRect.offsetBy(toFrame)(dx: toFrame.size.width * ofDx * -1, dy: toFrame.size.height * ofDy * -1)
       transitionContext.containerView.addSubview(toView)
    
       let transitionDuration = self.transitionDuration(using: transitionContext)
       UIView.animate(withDuration: transitionDuration, animations: { //動畫
           
           formView.frame = CGRect.offsetBy(fromFrame)(dx: fromFrame.size.width * ofDx * 1, dy: fromFrame.size.height * ofDy * 1)
           toView.frame = toFrame;
    
       }) { (_) in
           transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
       }
    }
}

效果預覽(GIF)

2614444-ab71465a126d816c.gif
效果預覽- 慢

OC版地址:自定義TabBar動畫效果 - 頁面轉場

部落格地址

兩個版本程式碼的專案地址:GitHub

相關文章