最近快要過節了,因此項目中有一個需求,四個按鈕的image經過後臺返回的圖片來進行配置。同時中間的凸起按鈕是否展示也經過後臺來配置。git
由於項目比較急,之前沒有中間凸起按鈕的設計,因此首先考慮實現的是新建一個繼承UITaBar的類,而後經過valueForKeyPath來替換系統的tabbar。github
自定義WWTabBar面試
class WWTabBar: UITabBar {
var oldSafeAreaInsets = UIEdgeInsets.zero
// tabbar高度49
let TabbarHeight: CGFloat = 49.0
let centerWidth: CGFloat = 62.0
let centerHeight: CGFloat = 48.0
// 中間按鈕
public var centerBtn: UIButton = UIButton(type: .custom)
// 中間按鈕圖片url
var centerImageUrl: String? {
didSet {
centerBtn.kf.setImage(with: URL(string: centerImageUrl ?? ""), for: .normal)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
centerBtn.adjustsImageWhenHighlighted = false
addSubview(centerBtn)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
centerBtn.frame = CGRect(x: (UIScreen.main.bounds.size.width - centerWidth) / 2, y: -5, width: centerWidth, height: centerHeight)
//系統自帶的按鈕類型是UITabBarButton,找出這些類型的按鈕,而後從新排布位置,空出中間的位置
let btnWidth = self.frame.size.width / 5
for btn in self.subviews {
if btn.isKind(of: NSClassFromString("UITabBarButton")!.self) {
let label = btn.value(forKeyPath: "_label") as! UILabel
switch (label.text ?? "") {
case "首頁":
btn.frame = CGRect(x: 0,
y: 0,
width: btnWidth,
height: TabbarHeight)
case "探索":
btn.frame = CGRect(x: btnWidth,
y: 0,
width: btnWidth,
height: TabbarHeight)
case "發現":
btn.frame = CGRect(x: btnWidth * 3,
y: 0,
width: btnWidth,
height: TabbarHeight)
case "個人":
btn.frame = CGRect(x: btnWidth * 4,
y: 0,
width: btnWidth,
height: TabbarHeight)
default:
return
}
}
}
}
// 處理超出tabbar部分按鈕點擊無效的問題
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !self.isHidden {
// 轉換座標
let tempPoint = centerBtn.convert(point, from: self)
// 判斷點擊的點是否在按鈕區域內
if centerBtn.bounds.contains(tempPoint) {
// 返回按鈕
return centerBtn
}
}
return super.hitTest(point, with: event)
}
}
複製代碼
動態配置中間按鈕,自定義UITabBarController。若是配置中間按鈕,使用WWTabar替換,若不配置,使用默認TabBar。 爲了擴展性,咱們先定義一個WWTabBarControllerbash
class WWTabBarController: UITabBarController {
var isShow = false
var tabIcon: UIImage?
var tabIconUrl: String?
var toUrl: String?
var customTabbar: WWTabBar?
init(isShowPlus: Bool, icon: UIImage?, iconUrl: String?, uri: String?) {
isShow = isShowPlus
tabIcon = icon
tabIconUrl = iconUrl
toUrl = uri
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
if isShow {
customTabbar = WWTabBar(frame: .zero)
setValue(customTabbar, forKeyPath: "tabBar")
customTabbar?.centerBtn.addTarget(self, action: #selector(centerBtnAction), for: .touchUpInside)
}
}
// 中間按鈕點擊
@objc func centerBtnAction() {
// LocalRouter.shared.open(url: toUrl ?? "")
}
}
複製代碼
這裏有中間按鈕的圖片、跳轉連接等等,經過isShow屬性來決定是否用自定義tabbar來替換系統的。中間按鈕路徑跳轉到toUrl,這裏須要本身的路由實現。 使用時,新建類來繼承這個WWTabBarController微信
class TestTabBarController: WWTabBarController {
override func viewDidLoad() {
super.viewDidLoad()
addChildViewControllers()
}
//添加子控制器
func addChildViewControllers() {
addChildViewController(ViewController(), title: "首頁", imageName: "tab1")
addChildViewController(ViewController(), title: "探索", imageName: "tab2")
addChildViewController(ViewController(), title: "發現", imageName: "tab3")
addChildViewController(ViewController(), title: "個人", imageName: "tab4")
}
// 添加子vc
func addChildViewController(_ childController: UIViewController, title: String, imageName: String) {
childController.title = title
if imageName.count > 0{
childController.tabBarItem.image = UIImage(named: imageName)
childController.tabBarItem.selectedImage = UIImage(named: imageName)
}
let nav = UINavigationController(rootViewController: childController)
addChild(nav)
}
}
複製代碼
在這裏配置四個tabbaritem和對應的頁面 使用時,從後臺拿到配置,而後進行初始化網絡
self.window?.rootViewController = TestTabBarController(isShowPlus: false, icon: nil, iconUrl: nil, uri: nil)
複製代碼
self.window?.rootViewController = TestTabBarController(isShowPlus: true, icon: image, iconUrl: "iconurl", uri: "yoururl")
複製代碼
由於可能會碰見網絡很差的狀況。因此項目一開始使用系統的TabBar,請求配置文件並保存下來。第二次再使用本地的配置文件來初始化。因此我建議不要直接使用URl來加載圖片,將圖片down下來而後設置到TabBar中。在上面的WWTabBar中我是設置的url,須要修改一下。ide
因爲咱們項目中首頁對應的TabBarItem Icon是會變化的,再滑動必定距離後,首頁Icon會變成刷新圖標,因此會再次調用layoutSubviews方法,這個layout過程會被用戶看見,因此這個方法不可行。因此嘗試自定義View,不繼承系統UITabBar。 這裏先挖個坑。若是沒有這個需求,能夠用上述方法。 github.com/FrunkPiano/…ui
最近加了一些iOS開發相關的QQ羣和微信羣,可是感受都比較水,裏面對於技術的討論比較少,因此本身建了一個iOS開發進階討論羣,歡迎對技術有熱情的同窗掃碼加入,加入之後你能夠獲得:url