Swift - 002 自定義TabBar

前言:

第一次用Swift學習寫一個自定義Tabbar,不知道理的清楚不慎颗。不同的代碼敲的還有點小亂,慢慢磨吧腹泌。

目錄:

001 - 自定義TabBar大概過程
002 - 核心代碼

自定義TabBar步驟

1.創(chuàng)建一個tabBar控制器嘶卧,把他作為窗口的根控制,并顯示。

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
         // Override point for customization after application launch.
   
   window = UIWindow(frame: UIScreen.main.bounds)
   window?.rootViewController = LLTabBarViewController()
   window?.backgroundColor = UIColor.white
   window?.makeKeyAndVisible()
   
   return true
   }

效果圖:


2.我們自定義一個繼承于UITabBar的Tabbar類,并利用KVC將系統(tǒng)的Tabbar替換掉凉袱。

 import UIKit
 
 class ZBTabBarController: UITabBarController {
 
     var TabBar = ZBTabBar()
     
     
     override func viewDidLoad() {
         super.viewDidLoad()
         self.creatTabBar()
         
     }
     
     func creatTabBar() {
         let customTabBar: ZBTabBar = ZBTabBar()
       
         self.setValue(customTabBar, forKey: "tabBar")
         TabBar = customTabBar
     }
     
 }

3.根據(jù)標題數(shù)量芥吟,便利添加子控制器侦铜,并配置其基本信息。

     func setRootTaBarVc() {
             
             var Vc: UIViewController?
             
             for i in 0 ..< self.tabBarTitles.count {
                 print(self.tabBarTitles[i])
                switch i {
                case 0:
                     Vc = ZBInkDropController()
                 case 1:
                     Vc = ZBExchangeController()
                 case 2:
                     Vc = ZBTreasureHuntController()
                 case 3:
                     Vc = ZBMineController()
                 default:
                     break
                 }
                 
                 // 1.創(chuàng)建導航控制器
                 let nav = ZBRootNavController.init(rootViewController: Vc!)
                 // 2.創(chuàng)建tabbarItem
                 let barItem = UITabBarItem.init(title: self.tabBarTitles[i], image: UIImage.init(named: self.tabBarNormalImgs[i])?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage.init(named: self.tabBarSelectImgs[i])?.withRenderingMode(.alwaysOriginal))
                 
                 // 3.更改字體顏色
                 barItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:RGBAlpa(128,128,128,1)], for:.normal )
                 barItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:RGBAlpa(0,0,0,1)], for: .selected)
                 
                 // 設置標題
                 Vc?.title = self.tabBarTitles[i]
                 
                 // 設置根控制器
                 Vc?.tabBarItem = barItem
                 
                 // 添加到當前控制器
                 self.addChild(nav)
                 
             }
         }
         
     }

效果圖如下:


4.根據(jù)標題數(shù)量钟鸵,便利添加子控制器钉稍,并配置其基本信息

  class ZBTabBar: UITabBar {
    
      // 懶加載創(chuàng)建一個中間按鈕
      private lazy var addButton:UIButton = {
          return UIButton()
      }()
      
      // 視圖初始化
      override init(frame: CGRect) {
          
          super.init(frame: frame)
          
          addButton.setBackgroundImage(UIImage.init(named: "tabbar_margin_img"), for: .normal)
          addButton.addTarget(self, action: #selector(ZBTabBar.addButtonClick), for: .touchUpInside)
          self.addSubview(addButton)
          self.backgroundImage =  UIColor.creatImageWithColor(color: UIColor.white)
        
        
      }
      
      required init?(coder aDecoder: NSCoder) {
          fatalError("init(coder:) has not been implemented")
      }
      
     // 點擊中間按鈕的實現(xiàn)方法
      @objc func addButtonClick() {
          print("我點擊了中間的按鈕")
          
      }
      
      
      // 調用布局約束方法
      override func layoutSubviews() {
          super.layoutSubviews()
          
          let buttonX = SCREEN_WIDTH / 5
          var index = 0
          
          for barButton in self.subviews {
              if barButton.isKind(of: NSClassFromString("UITabBarButton")!) {
                  
                  if index == 2 {
                      /// 設置添加按鈕位置
                      addButton.frame.size = CGSize.init(width: (addButton.currentBackgroundImage?.size.width)!, height: (addButton.currentBackgroundImage?.size.height)!)
                      addButton.center = CGPoint.init(x: self.center.x, y: self.frame.size.height/2 - 15)
                      index += 1
                  }
                  
                  barButton.frame = CGRect.init(x: buttonX * CGFloat(index), y: 0, width: buttonX, height: self.frame.size.height)
                  index += 1
                 
              }
              
          }
              
           self.bringSubviewToFront(addButton)
      
      }
      
      
  }

效果圖如下:


5.接下來,我們會發(fā)現(xiàn)棺耍,點擊中間按鈕超出父類的部分不能點擊贡未,所以我們做的是重寫hitTest方法,監(jiān)聽按鈕的點擊 讓凸出tabbar的部分響應點擊蒙袍。

    /// 重寫hitTest方法俊卤,監(jiān)聽按鈕的點擊 讓凸出tabbar的部分響應點擊
        override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        
            // 判斷是否為根控制器
            if self.isHidden {
                // tabbar隱藏 不在主頁 系統(tǒng)處理
                return super.hitTest(point, with: event)
            }else {
                
                // 將單線觸摸點轉換到按鈕上生成新的點
                let onButton = self.convert(point, to: self.addButton)
                // 判斷新的點是否在按鈕上
                if self.addButton.point(inside: onButton, with: event) {
                    return addButton
                }else {
                // 不再按鈕上 系統(tǒng)處理
                    return super.hitTest(point, with: event)
                    
                }
            
            }

6.最后,我們創(chuàng)建一個代理事件害幅,讓按鈕的點擊由控制器去代理瘾蛋,執(zhí)行點擊事件。

   protocol RootTabBarDelegate :NSObjectProtocol{
       func addClick()
   }

   // 點擊中間按鈕的實現(xiàn)方法
       @objc func addButtonClick() {
           
           if addDelegate != nil{
               addDelegate?.addClick()
               
           }
       }

7.tabbar控制器矫限,設置哺哼、遵守代理就ok了。

核心代碼


ZBTabBarController.swift

 class ZBTabBarController: UITabBarController,RootTabBarDelegate {
    
     // 點擊中間按鈕的方法
     func addClick() {
         print("點擊中間按鈕的方法")
     }
     
 
     var TabBar = ZBTabBar()
     var tabBarNormalImgs = ["1","2","3","4"]
     var tabBarSelectImgs = ["1","2","3","4"]
     var tabBarTitles = ["墨滴","兌換","尋寶","我的"]
         
         override func viewDidLoad() {
             super.viewDidLoad()
     
             self.creatTabBar()
             
         }
         
         func creatTabBar() {
             
             // 替換系統(tǒng)Tabbar
             let customTabBar: ZBTabBar = ZBTabBar()
             customTabBar.addDelegate = self
             self.setValue(customTabBar, forKey: "tabBar")
             TabBar = customTabBar
             // 設置tabbar子控制器
             self.setRootTaBarVc()
             
         }
         
         func setRootTaBarVc() {
             
             var Vc: UIViewController?
             
             for i in 0 ..< self.tabBarTitles.count {
                 print(self.tabBarTitles[i])
                 switch i {
                 case 0:
                     Vc = ZBInkDropController()
                 case 1:
                     Vc = ZBExchangeController()
                 case 2:
                     Vc = ZBTreasureHuntController()
                 case 3:
                     Vc = ZBMineController()
                 default:
                     break
                 }
                 
                 // 1.創(chuàng)建導航控制器
                 let nav = ZBRootNavController.init(rootViewController: Vc!)
                 // 2.創(chuàng)建tabbarItem
                 let barItem = UITabBarItem.init(title: self.tabBarTitles[i], image: UIImage.init(named: self.tabBarNormalImgs[i])?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage.init(named: self.tabBarSelectImgs[i])?.withRenderingMode(.alwaysOriginal))
                 
                 // 3.更改字體顏色
                 barItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:RGBAlpa(128,128,128,1)], for:.normal )
                 barItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:RGBAlpa(0,0,0,1)], for: .selected)
                 
                 // 設置標題
                 Vc?.title = self.tabBarTitles[i]
                 
                 // 設置根控制器
                 Vc?.tabBarItem = barItem
                 
                 // 添加到當前控制器
                 self.addChild(nav)
                 
             }
         }
     }

ZBTabBar.swift

 import UIKit
 
 protocol RootTabBarDelegate :NSObjectProtocol{
     func addClick()
 }
 
 
 
 class ZBTabBar: UITabBar {
   
     weak var addDelegate: RootTabBarDelegate?
     
     // 懶加載創(chuàng)建一個中間按鈕
     private lazy var addButton:UIButton = {
         return UIButton()
     }()
     
     // 視圖初始化
     override init(frame: CGRect) {
         
         super.init(frame: frame)
         
         addButton.setBackgroundImage(UIImage.init(named: "tabbar_margin_img"), for: .normal)
         addButton.addTarget(self, action: #selector(ZBTabBar.addButtonClick), for: .touchUpInside)
         self.addSubview(addButton)
         self.backgroundImage =  UIColor.creatImageWithColor(color: UIColor.white)
       
       
     }
     
     required init?(coder aDecoder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
     
    // 點擊中間按鈕的實現(xiàn)方法
     @objc func addButtonClick() {
         
         if addDelegate != nil{
             addDelegate?.addClick()
             
         }
     }
     
     
     // 調用布局約束方法
     override func layoutSubviews() {
         super.layoutSubviews()
         
         let buttonX = SCREEN_WIDTH / 5
         var index = 0
         
         for barButton in self.subviews {
             if barButton.isKind(of: NSClassFromString("UITabBarButton")!) {
                 
                 if index == 2 {
                     /// 設置添加按鈕位置
                     addButton.frame.size = CGSize.init(width: (addButton.currentBackgroundImage?.size.width)!, height: (addButton.currentBackgroundImage?.size.height)!)
                     addButton.center = CGPoint.init(x: self.center.x, y: self.frame.size.height/2 - 15)
                     index += 1
                 }
                 barButton.frame = CGRect.init(x: buttonX * CGFloat(index), y: 0, width: buttonX, height: self.frame.size.height)
                 index += 1
                
             }
             
         }
             
          self.bringSubviewToFront(addButton)
     
     }
     
     
      /// 重寫hitTest方法叼风,監(jiān)聽按鈕的點擊 讓凸出tabbar的部分響應點擊
     override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
     
         // 判斷是否為根控制器
         if self.isHidden {
             // tabbar隱藏 不在主頁 系統(tǒng)處理
             return super.hitTest(point, with: event)
         }else {
             
             // 將單線觸摸點轉換到按鈕上生成新的點
             let onButton = self.convert(point, to: self.addButton)
             // 判斷新的點是否在按鈕上
            if self.addButton.point(inside: onButton, with: event) {
               return addButton
            }else {
             // 不再按鈕上 系統(tǒng)處理
                 return super.hitTest(point, with: event)
                 
             }
         
         }
         
         
     }
     
 }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末取董,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子无宿,更是在濱河造成了極大的恐慌茵汰,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孽鸡,死亡現(xiàn)場離奇詭異蹂午,居然都是意外死亡,警方通過查閱死者的電腦和手機彬碱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門豆胸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巷疼,你說我怎么就攤上這事晚胡。” “怎么了嚼沿?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵估盘,是天一觀的道長。 經(jīng)常有香客問我骡尽,道長遣妥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任攀细,我火速辦了婚禮箫踩,結果婚禮上爱态,老公的妹妹穿的比我還像新娘。我一直安慰自己班套,他們只是感情好肢藐,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布故河。 她就那樣靜靜地躺著吱韭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鱼的。 梳的紋絲不亂的頭發(fā)上理盆,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音凑阶,去河邊找鬼猿规。 笑死,一個胖子當著我的面吹牛宙橱,可吹牛的內容都是我干的姨俩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼师郑,長吁一口氣:“原來是場噩夢啊……” “哼环葵!你這毒婦竟也來了?” 一聲冷哼從身側響起宝冕,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤张遭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后地梨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菊卷,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年宝剖,在試婚紗的時候發(fā)現(xiàn)自己被綠了洁闰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡万细,死狀恐怖渴庆,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情雅镊,我是刑警寧澤襟雷,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站仁烹,受9級特大地震影響耸弄,放射性物質發(fā)生泄漏。R本人自食惡果不足惜卓缰,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一计呈、第九天 我趴在偏房一處隱蔽的房頂上張望砰诵。 院中可真熱鬧,春花似錦捌显、人聲如沸茁彭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽理肺。三九已至,卻和暖如春善镰,著一層夾襖步出監(jiān)牢的瞬間妹萨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工炫欺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乎完,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓品洛,卻偏偏與公主長得像树姨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子桥状,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內容