原文連接:仿微博 iOS 客戶端 TabBar 中間按鈕
項目源碼:模仿微博客戶端項目源碼ios
我在模仿微博 iOS 客戶端。如圖:git
微博客戶端 TabBar 中間按鈕和其餘按鈕不同,一個是樣式不同,一個是點擊事件不同。github
第一個想法實際上是建一個 UITabBarController 的子類,自定義 TabBar 的樣式,可是由於還沒學習過,因此此次但願另找一個辦法。swift
第二個想法是用一個 button 覆蓋 TabBar 中間按鈕。無非就是在代碼裏新建一個UIButton
,用CGRectMake()
定位。ide
有了上面的思路,我就在首頁的 ViewController 中的viewDidLoad()
方法中添加了以下代碼:post
//100px 高寬隨便設置用來測試的。 let postBtn = UIButton() postBtn.frame = CGRectMake(self.view.frame.width/2 - 50, self.view.frame.height - 100, 100, 100) postBtn.setBackgroundImage(UIImage(named: "post_btn"), forState: .Normal) self.view.addSubview(postBtn)
結果如圖:學習
兩個問題測試
按鈕被什麼東西擋住了?動畫
這個按鈕添加在首頁的 View 裏面,因此只有首頁有,其餘 tab 怎麼辦?每一個 tab 寫一個嗎?spa
問題一
在 Tabbed Application,底部始終有一個在最上層的 TabBar。每個 tab 頁面的 view 都在 TabBar 下面,因此在 tab 頁面的 view 中在 TabBar 所在的位置添加子 subview,subview 會被蓋住。
因此思路二行不通了嗎?
問題二
重複一點代碼倒沒什麼,不過有沒有辦法避免呢?
我發現做爲 Initial View Controller 的這個 Tab Bar View Controller 也能夠添加一個自定義的 ViewController。
因而我新建了一個 UITabBarController 的子類。在viewDidLoad()
中添加了 button。下面的代碼是調整過 button 大小位置後的最終代碼。
// TabBarViewController.swift import UIKit class TabBarViewController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() // 初始化一些要用到的參數 let WINDOW_HEIGHT = self.view.frame.height let TAB_HEIGHT = self.tabBar.frame.height let GRID_WIDTH = self.view.frame.width / 5 let MARGIN_X = CGFloat(2) let MARGIN_Y = CGFloat(5) let BTN_WIDTH = TAB_HEIGHT - MARGIN_X * 2 let BTN_HEIGHT = TAB_HEIGHT - MARGIN_Y * 2 // 遮罩層,用於遮擋本來的 TabBarItem let modalView = UIView() modalView.frame = CGRectMake(GRID_WIDTH * 2, WINDOW_HEIGHT - TAB_HEIGHT, GRID_WIDTH, TAB_HEIGHT) self.view.addSubview(modalView) // 添加自定義按鈕 let postBtn = UIButton() postBtn.frame = CGRectMake(GRID_WIDTH * 2 + (GRID_WIDTH - BTN_WIDTH) / 2, WINDOW_HEIGHT - TAB_HEIGHT + MARGIN_Y, BTN_WIDTH, BTN_HEIGHT) postBtn.setBackgroundImage(UIImage(named: "post_btn"), forState: .Normal) self.view.addSubview(postBtn) // 給按鈕添加事件 postBtn.addTarget(self, action: "postButtonClicked:", forControlEvents: .TouchUpInside) } }
效果如圖:
對於問題一
由於是直接在 TabBarController 的 view 上添加 subview,因此按鈕正常顯示。
對於問題二
由於 TabBar 是全部 tab 頁面公用的,因此不用在每一個頁面單獨添加按鈕。
遮罩層的做用
由於自定義按鈕的大小沒有覆蓋 TabBar 中間 item 的大小,因此點擊邊緣部分會進入對應的 tab 頁面。而微博客戶端這個按鈕點擊後,應該是出現以下頁面,而非進入 tab 頁。因此用遮罩層擋住那個 TabBar item。
自定義按鈕的點擊事件
這個加號按鈕點擊完以後應該是出現一個半透明視圖,包含一些按鈕。因此我在最後給按鈕添加了一個點擊事件,負責完成顯示新視圖及其中的動畫。
若是對這個半透明視圖和其中動畫的實現有興趣,能夠到我 github 下載源碼看看。由於都是最基本的 Animation,因此可能不會單獨寫一篇分享。
我的以爲值得注意的是,個人解決方案是:這個半透明視圖在第一次出現以後就保存在 TabBarViewController 的類成員變量裏,以後的關閉和再顯示只是將視圖的 alpha 值在 0 和 1 之間切換。
說不定也會總結一次。由於實現過程當中踩到一些跟 Animation 有關的坑,好比有些屬性變換是當即執行的,不能用動畫漸變實現。