最近快要过节了,因此项目中有一个需求,四个按钮的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