本文是剛學(xué)習(xí)swift后宙拉,第一個(gè)練手的項(xiàng)目,主要目的是將學(xué)到的swift知識(shí)去完成一個(gè)簡(jiǎn)易的自定義tabbar
先看效果
總效果圖
然后我們?cè)谝粚右粚涌?/p>
根據(jù)自己的需求,用CGContext 畫的背景圖
中間的tabBarItem不設(shè)置圖片醇锚,只設(shè)置文字
在tabbar上的背景圖上插入自定義的控件
這里自定義的控件是button
到這里贼穆,總結(jié)下就是题山,
我們自定義的tabbar,根據(jù)需求添加一個(gè)背景圖故痊,然后在插入我們自定義的控件到正確的位置上即可顶瞳,其他的都沿用原生的tabbar,因?yàn)樽远x控件會(huì)擋住原生tabbaritem愕秫,所以需要單獨(dú)為我們自定義的控件添加點(diǎn)擊事件(后面會(huì)講道自定義控件的點(diǎn)擊事件)慨菱。
代碼:
class CustomTabbar: UITabBar {
private lazy var centerBtn: UIButton = {
let btn = UIButton.init(type: .custom)
btn.setImage(UIImage.initWithOriginalMode(named: "tab_diy"), for: .normal)
btn.setImage(UIImage.initWithOriginalMode(named: "tab_diy_sel"), for: .selected)
btn.sizeToFit()
btn.imageEdgeInsets = UIEdgeInsets.init(top: -10, left: 0, bottom: 0, right: 0)
btn.addTarget(self, action: #selector(clickAtItem), for: .touchUpInside)
return btn
}()
weak open var clickDelegate: CustomTabbarDelegate?
...
override init(frame: CGRect) {
super.init(frame: frame)
// 添加背景圖
let backV = UIImageView.init(frame: CGRect.init(x: 0, y: -26, width: ScreenW, height: 75))
backV.backgroundColor = UIColor.clear
self.addSubview(backV)
// 自己繪制的背景圖
let img = drawCustomTabbarBackImg()
backV.image = img
// 添加自定義的btn控件
self.addSubview(centerBtn)
}
override func layoutSubviews() {
super.layoutSubviews()
// 重新計(jì)算自定義btn控件的位置
centerBtn.frame = CGRect.init(x: ScreenW/5*2, y: -26, width: ScreenW/5, height: 75)
self.bringSubviewToFront(centerBtn)
}
@objc func clickAtItem(btn: UIButton) {
// btn 點(diǎn)擊之后狀態(tài)給反轉(zhuǎn)下
btn.isSelected = !btn.isSelected
// 讓代理去實(shí)現(xiàn)點(diǎn)擊事件。
clickDelegate?.clickTabbarItem((self, centerBtn))
}
## 重寫hitTest方法戴甩,去監(jiān)聽中間按鈕點(diǎn)擊符喝,目的是為了讓凸出的部分點(diǎn) 擊也有反應(yīng) ##
## 當(dāng)然你的視圖不超出父視圖,這個(gè)也可以不寫 ##
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !self.isHidden, centerBtn.frame.contains(point) {
return centerBtn
}
// 記得把centerbtn 設(shè)置成 nomal狀態(tài)
centerBtn.isSelected = false
return super.hitTest(point, with: event)
}
}
}}
有一個(gè)代理的注意點(diǎn)甜孤,(畢竟初學(xué)swift协饲,還是有必要提一下)
## OC 中代理都是用 weak 修飾 防止循環(huán)引用,這里也要遵守 ##
weak open var clickDelegate: CustomTabbarDelegate?
@objc func clickAtItem(btn: UIButton) {
// btn 點(diǎn)擊之后狀態(tài)給反轉(zhuǎn)下
btn.isSelected = !btn.isSelected
// 讓代理去實(shí)現(xiàn)點(diǎn)擊事件缴川。
clickDelegate?.clickTabbarItem((self, centerBtn))
}
## :后面的 class囱稽,指定只能給class用不能給值類型用 ##
protocol CustomTabbarDelegate: class {
func clickTabbarItem(_: (Any));
}
接下來就是 tabbarController 里面替換成我們自定義的tabbar了
關(guān)鍵一句就是:
self.setValue(customTab, forKey: "tabBar")
class BaseTabVC: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
self.customTabbar()
let temple = (titles: ["首頁", "分類", "DIY", "圈子", "我的"], images: ["tab_home", "tab_material", "", "tab_social", "tab_my"])
let vcs = [HomeVC.init(), MaterialVC.init(), DIYVC.init(), SocialVC.init(), ProfileVC.init()].enumerated().map { (idx, vc) -> UIViewController in
self.controller(createTabbarItemWith: vc, title: temple.titles[idx], image: temple.images[idx])
let nav = BaseNavVC.init(rootViewController: vc)
return nav
}
self.viewControllers = vcs
}
func customTabbar() {
let customTab = CustomTabbar.init(frame: CGRect.init(x: 0, y: ScreenH - TabbarH, width: ScreenW, height: TabbarH))
// 別忘了實(shí)現(xiàn)代理
customTab.clickDelegate = self
self.setValue(customTab, forKey: "tabBar")
## 這里還是我們熟悉的調(diào)整tabbar 上面的一些屬性 ##
## 根據(jù)我們的需求調(diào)整就行 ##
//調(diào)整tabbar 上面橫線陰影顏色
self.tabBar.backgroundImage = UIImage.init()
self.tabBar.shadowImage = UIImage.init();
self.tabBar.barTintColor = HEX(hexValue: 0xFFFFFF)
self.tabBar.tintColor = HEX(hexValue: 0x0D57F6)
self.tabBar.unselectedItemTintColor = HEX(hexValue: 0x000000)
self.tabBar.isTranslucent = false
}
...
切換tabBarItem的方法
self.selectedIndex = 2
// 擴(kuò)展里面, 實(shí)現(xiàn) 點(diǎn)擊 customTabbar 的代理
extension BaseTabVC: CustomTabbarDelegate {
func clickTabbarItem(_: (Any)) {
guard let vc = self.viewControllers?[2] else { return }
## 切換當(dāng)前tabitem 到我們需要的控制器 ##
self.selectedIndex = 2
}
}
寫在最后,實(shí)現(xiàn)自定義的tabbar 可以有很多種思路二跋,復(fù)雜的可以寫一個(gè)view 替換掉tabbar战惊,然后將系統(tǒng)的tabbar 給隱藏掉,都是可以的扎即,只不過需要實(shí)現(xiàn)tabbar所有的功能吞获,會(huì)比較繁瑣。這個(gè)自定義的好處是谚鄙,整體代碼量不多各拷,思路實(shí)現(xiàn)也不復(fù)雜,主要是不影響原生tabbar的功能闷营。