本文是刚学习swift后,第一个练手的项目,主要目的是将学到的swift知识去完成一个简易的自定义tabbar
先看效果
然后我们在一层一层看
到这里,总结下就是,
我们自定义的tabbar,根据需求添加一个背景图,然后在插入我们自定义的控件到正确的位置上即可,其他的都沿用原生的tabbar,因为自定义控件会挡住原生tabbaritem,所以需要单独为我们自定义的控件添加点击事件(后面会讲道自定义控件的点击事件)。
代码:
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()
// 重新计算自定义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 点击之后状态给反转下
btn.isSelected = !btn.isSelected
// 让代理去实现点击事件。
clickDelegate?.clickTabbarItem((self, centerBtn))
}
## 重写hitTest方法,去监听中间按钮点击,目的是为了让凸出的部分点 击也有反应 ##
## 当然你的视图不超出父视图,这个也可以不写 ##
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !self.isHidden, centerBtn.frame.contains(point) {
return centerBtn
}
// 记得把centerbtn 设置成 nomal状态
centerBtn.isSelected = false
return super.hitTest(point, with: event)
}
}
}}
有一个代理的注意点,(毕竟初学swift,还是有必要提一下)
## OC 中代理都是用 weak 修饰 防止循环引用,这里也要遵守 ##
weak open var clickDelegate: CustomTabbarDelegate?
@objc func clickAtItem(btn: UIButton) {
// btn 点击之后状态给反转下
btn.isSelected = !btn.isSelected
// 让代理去实现点击事件。
clickDelegate?.clickTabbarItem((self, centerBtn))
}
## :后面的 class,指定只能给class用不能给值类型用 ##
protocol CustomTabbarDelegate: class {
func clickTabbarItem(_: (Any));
}
接下来就是 tabbarController 里面替换成我们自定义的tabbar了
关键一句就是:
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))
// 别忘了实现代理
customTab.clickDelegate = self
self.setValue(customTab, forKey: "tabBar")
## 这里还是我们熟悉的调整tabbar 上面的一些属性 ##
## 根据我们的需求调整就行 ##
//调整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
// 扩展里面, 实现 点击 customTabbar 的代理
extension BaseTabVC: CustomTabbarDelegate {
func clickTabbarItem(_: (Any)) {
guard let vc = self.viewControllers?[2] else { return }
## 切换当前tabitem 到我们需要的控制器 ##
self.selectedIndex = 2
}
}
写在最后,实现自定义的tabbar 可以有很多种思路,复杂的可以写一个view 替换掉tabbar,然后将系统的tabbar 给隐藏掉,都是可以的,只不过需要实现tabbar所有的功能,会比较繁琐。这个自定义的好处是,整体代码量不多,思路实现也不复杂,主要是不影响原生tabbar的功能。