自定义TabBar动画效果 - 页面转场(Swift)

前言:之前写过一篇自定义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)

效果预览- 慢

OC版地址:自定义TabBar动画效果 - 页面转场

博客地址

两个版本代码的项目地址:GitHub

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 文/林子 电视机里赵忠祥老师用独具魅力的磁性嗓音在解说自然界中食物链的游戏规则:在辽阔的非洲草原上,一只雄性的狮子...
    芝麻的微光阅读 295评论 0 3
  • 每次看剧里人吃牛肉, 内心几乎是奔溃的。 牛肉的好吃都要溢出屏幕了, 好饿好饿,我开始吞口水了! 完全控制不住想吃...
    菊厂酒馆阅读 485评论 0 1
  • 终于把拖了很久的一件事办了,来回路上耗时4个小时。 说不清楚内心深处是什么感觉 隐隐的有一种怀疑,房奴的身份负担的...
    伊卡洛斯林阅读 153评论 0 1