在實際開發中,系統的原生控件并不能滿足我們的需求,這個時候就需要自己去自定義這個控件,自定義控件需要自己對原生控件結構非常了解。今天,這裡來講一下不同尋常的tabBar。
原則:盡量利用系統自帶的TabBar.隻改需要改的地方
不同尋常的tabBar 類型一:這種基本上是重寫了整個tabbar,然後根據自己的需求來定義view的風格
步驟:
1.把自帶的TaBBar條給隐藏掉,添加自己的view
let rect = self.tabBar.frame
self.tabBar.removeFromSuperview()
customTabBar = CustomTabBar()
customTabBar.customDelegate = self
customTabBar.frame = rect
self.view.addSubview(customTabBar)
2.自己做一個View,上面放幾個按鈕,設定按鈕的點選事件,并設定selectIndex
import UIKit
protocol GGTabBarDelegate: NSObjectProtocol {
func tabBarSelectedFromBtnIndexToBtnIndex(tabBar:CustomTabBar,fromBtnIndex:Int,toBtnIndex:Int)
}
class CustomTabBar: UIView {
weak var customDelegate:GGTabBarDelegate?
/**
* 設定之前選中的按鈕
*/
var selectedBtn:ItemButton?
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.whiteColor() //設定tabBar的背景色
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func addItemBtn(image:UIImage,selectedImage:UIImage,title:String) -> Void {
let itemBtn = ItemButton(frame: CGRectZero)
itemBtn.titleLabel?.font = UIFont.systemFontOfSize()
itemBtn.setImage(image, forState: .Normal)
itemBtn.setImage(selectedImage, forState: .Selected)
itemBtn.setTitle(title, forState: .Normal)
itemBtn.addTarget(self, action: #selector(CustomTabBar.btnClicked(_:)), forControlEvents: .TouchUpInside)
self.addSubview(itemBtn)
//規定預設選中按鈕
if self.subviews.count == {
btnClicked(itemBtn)
}
}
func btnClicked(btn:ItemButton) -> Void {
//設定目前選中的按鈕
selectedBtn?.selected = false
btn.selected = true
selectedBtn = btn
if ((customDelegate?.respondsToSelector(Selector("tabBarSelectedFromBtnIndexToBtnIndex:fromBtnIndex:toBtnIndex:"))) != nil) {
customDelegate?.tabBarSelectedFromBtnIndexToBtnIndex(self, fromBtnIndex: (selectedBtn?.tag)!, toBtnIndex: btn.tag)
}
}
override func layoutSubviews() {
super.layoutSubviews()
let width = self.bounds.size.width
let height = self.bounds.size.height
let count = self.subviews.count
for i in .<count {
let btn = self.subviews[i] as! ItemButton
btn.tag = i
let x = CGFloat(i) * width / CGFloat(count)
let w = width / CGFloat(count)
btn.frame = CGRect(x: x, y: , width: w, height: height)
}
}
在這裡為了更好的實作自定義的效果,用了自定義的按鈕,讓按鈕圖檔文字上下居中顯示
import UIKit
class ItemButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.setTitleColor(UIColor.grayColor(), forState: .Normal) //normal title color
self.setTitleColor(UIColor.orangeColor(), forState: .Selected)//selected title color
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
//imageView
var center = self.imageView?.center
center?.x = self.frame.size.width / 2
center?.y = (self.imageView?.frame.size.height)! / 2 + 2.5
self.imageView?.center = center!
//titleLabel
var rect = self.titleLabel?.frame
rect?.origin.x = 0
rect?.origin.y = (self.imageView?.frame.size.height)!
rect?.size.width = self.frame.size.width
self.titleLabel?.frame = rect!
self.titleLabel?.textAlignment = .Center
}
}
3.關聯各個childViewController,覆寫相關事件
func addChildVC(childVC:UIViewController,title:String,imageName:String,selectedImageName:String) -> Void {
customTabBar.addItemBtn(UIImage(named: imageName)!, selectedImage: UIImage(named: selectedImageName)!, title: title)
//添加導航控制器
let nav = UINavigationController(rootViewController: childVC)
self.addChildViewController(nav)
}
func tabBarSelectedFromBtnIndexToBtnIndex(tabBar: GGAnotherTabBar, fromBtnIndex: Int, toBtnIndex: Int) {
self.selectedIndex = toBtnIndex
}
上面這種自定義之後,又需要在push的時候隐藏掉tabBar,這個時候我們需要寫一個來隐藏的方法,在push之前設為
hide = true
,在pop(或者viewAppear裡)設為
hide = false
import UIKit
extension UIViewController {
func hidesCustomBarWhenPushed(hide:Bool) -> Void {
let tabBarController = self.tabBarController as! MainViewController
let customTabBar = tabBarController.customTabBar
if hide {
// UIView.animateWithDuration(, animations: {
// UIView.setAnimationCurve(.EaseOut)
customTabBar.frame.origin.x = - UIScreen.mainScreen().bounds.width
// })
}else {
// UIView.animateWithDuration(, animations: {
// UIView.setAnimationCurve(.EaseOut)
customTabBar.frame.origin.x =
// })
}
}
}
在這裡,一直想用動畫的形式來表現,無奈做不出系統那麼好的效果,就幹脆去掉了動畫
不同尋常的tabBar 類型二:怎麼說呢,就是網上流傳的和新浪微網誌那樣的,這種就比較簡單了,不需要重寫整個tabBar,隻需要繼承自UITabBar,然後在初始化的時候,添加一個特殊按鈕(就是因為這個按鈕特殊,是以才需要自定義),并綁定點選事件用代理回調,最後在layoutSubviews()方法裡設定位置布局.
override init(frame: CGRect) {
super.init(frame: frame)
let btn = UIButton()
//configure the special button
plusBtn = btn
}
override func layoutSubviews() {
super.layoutSubviews()
//設定中間按鈕的位置
plusBtn?.center.x = self.frame.size.width *
plusBtn?.center.y = self.frame.size.height *
//設定其他item的位置
let w = self.frame.size.width / /這裡一共為個
var itemIndex =
for item in self.subviews {
let c = NSClassFromString("UITabBarButton")
if item.isKindOfClass(c!) {
item.frame.origin.x = (CGFloat)(itemIndex) * w
item.frame.size.width = w
itemIndex +=
if itemIndex == {
itemIndex +=
}
}
}
}
tabBar自定義完成後,我們使用KVC的形式來将customTabBar設為UITabBarController的tabBar:
let tabBar = CustomTabBar()
tabBar.customDelegate = self
////////kvc
self.setValue(tabBar, forKey: "tabBar")
添加子控制器部分代碼
func addChildVC(childVC:UIViewController,title:String,imageName:String,selectedImageName:String) -> Void {
childVC.tabBarItem.title = title
childVC.tabBarItem.image = UIImage(named: imageName)
childVC.tabBarItem.selectedImage = UIImage(named: selectedImageName)?.imageWithRenderingMode(.AlwaysOriginal)
//文字選中和未選中顔色
childVC.tabBarItem.setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.grayColor()], forState: .Normal)
childVC.tabBarItem.setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.orangeColor()], forState: .Selected)
//添加導航控制器
let nav = UINavigationController(rootViewController: childVC)
self.addChildViewController(nav)
}
func tabBarDidClickPlusButton(tabBar: GGTabBar) {
self.presentViewController(AddViewController(), animated: true, completion: nil)
}
不同尋常的tabBar 類型三:沒有什麼比較特殊的,現在我就想最中間那個item不顯示title,顯示一個巨大的image,來表明這個子產品就是要吸引你的注意O__O “…,這裡說一個最簡單的方法,在StoryBoard裡 拖一個tabBarController和幾個子控制器
将那個與衆不同的item的title去掉,image,selectedImage照常設定,
下面進入代碼部分
class MainTabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
for childVC in self.viewControllers! {
childVC.tabBarItem.image = childVC.tabBarItem.image?.imageWithRenderingMode(.AlwaysOriginal)
childVC.tabBarItem.selectedImage = childVC.tabBarItem.selectedImage?.imageWithRenderingMode(.AlwaysOriginal)
childVC.tabBarItem.setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.grayColor()], forState: .Normal) //normal title color
childVC.tabBarItem.setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.orangeColor()], forState: .Selected) //selected title color
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for i in .<(self.viewControllers?.count)! {
if i == {
let vc = self.viewControllers![i]
vc.tabBarItem.imageInsets = UIEdgeInsets(top: , left: , bottom: -, right: )
}
}
}
另附上:(這裡是使用系統的tabBar,也就說這個tabBarViewController的tabBar并沒有被removeFromSuperView或者Hidden=true)
nav push到下一個vc的時候隐藏tabBar, 傳回時顯示tabBar,隻需要這樣做:
self.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(nextVC, animated: true)
self.hidesBottomBarWhenPushed = false