-
想做个自己的tabBar, 自定义, 不想用系统UITabBar,这样会有一个问题hidesBottomBarWhenPushed到下个页面时无法隐藏, 没有系统自带的tabBar方便,找了很多资料加上,写了一个简单的,分享下
-
先上一张图片
image.png
系统tabBarController的结构发现, controller部分是放在UITransitionView上面, 想要自定义TabBar改变高度, 必须要改变这俩个的高度, 页面才能很好的适配,不至于出现controller无法铺满屏幕, 在viewDidLayoutSubviews里面去改变 tabBar的高度吗,可以获得你想要的高度, 图片可以我使用的是iconFont生成UIImage
贴上代码
- tabController中的代码
import UIKit
import SnapKit
class TabBarController: UITabBarController {
var selectButton: UIButton?
// var tabIcons = [UILabel]()
// var tabTitles = [UILabel]()
var newTab: UIView?
lazy var tabHeight: CGFloat = {
return CGFloat(isiPhoneX() ? (42 + 32) : 42)
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor=UIColor.white
setupChildController()
// setupTabBar()
}
func setupChildController() {
let home = BaseNavigationController(rootViewController: HomeViewController())
let market = BaseNavigationController(rootViewController: MarketViewController())
let classRoom = BaseNavigationController(rootViewController: ClassRoomViewController())
let collection = BaseNavigationController(rootViewController: CollectionViewController())
let mine = BaseNavigationController(rootViewController: MineViewController())
var controllerArray = [home, market, classRoom, collection, mine]
let iconArr = [Icon.Vegetables, Icon.Market, Icon.ClassRoom, Icon.Collection, Icon.Mine]
let titleArr = ["首页", "市集", "课堂", "收藏", "我的"]
for i in 0...controllerArray.count-1{
let controller = controllerArray[i]
controller.tabBarItem.title = titleArr[i]
let selectImage = UIImage(iconfont: iconArr[i].rawValue, fontSize: 7, color: UIColor.red)
selectImage.withRenderingMode(.alwaysOriginal)
controller.tabBarItem.selectedImage = selectImage
let normalImage = UIImage(iconfont: iconArr[i].rawValue, fontSize: 7, color: UIColor.purple)
controller.tabBarItem.image = normalImage.withRenderingMode(.alwaysOriginal)
}
self.viewControllers = controllerArray
//此处设置需注意, 设置了需要在Didlayoutsubviews里面去改变size要不会出现遮挡问题
//self.tabBar.backgroundImage = UIImage.imageWithColor(color: UIColor.white, size: self.tabBar.frame.size)
self.tabBar.tintColor = UIColor.red //选中是的颜色
self.tabBar.shadowImage = UIImage() //去除选择分割线
self.tabBar.unselectedItemTintColor = UIColor.purple
}
// func setupTabBar() {
// let rect = self.tabBar.frame
// print(rect)
// self.tabBar.removeFromSuperview()
// self.tabBar.isHidden = true
// newTab = UIView(frame: CGRect(x: 0, y: self.view.frame.size.height - tabHeight, width: rect.width, height: tabHeight))
// setupTabItems(tab: newTab!)
// newTab!.backgroundColor = UIColor.gray
// self.view.addSubview(newTab!)
// }
//
// func setupTabItems(tab: UIView) {
// let count = self.viewControllers?.count ?? 0
// let iconArr = [Icon.Home, Icon.Market, Icon.ClassRoom, Icon.Collection, Icon.Mine]
// let titleArr = ["首页", "市集", "课堂", "收藏", "我的"]
// let selectColor = UIColor.red
// let normalColor = UIColor.gray
// let width = view.frame.size.width / CGFloat(count)
// for i in 0...self.viewControllers!.count-1{
// let x = width * CGFloat(i)
// let item = UIView(frame: CGRect(x: x, y: 0, width: width, height: tabHeight))
// item.backgroundColor = UIColor.white
// let itemIcon = UILabel(iconfont: iconArr[i].rawValue, frame: CGRect(x: 0, y: 5, width: width, height: 25), fontSize: 24)
//// name.text = String(i)
// item.addSubview(itemIcon)
// let itemTitle = UILabel(frame: CGRect.zero)
// itemTitle.font = UIFont.systemFont(ofSize: 10)
// itemTitle.textAlignment = .center
// item.addSubview(itemTitle)
// itemTitle.snp.makeConstraints { (make) in
// make.height.equalTo(15)
// make.left.equalTo(itemIcon)
// make.right.equalTo(itemIcon)
// make.top.equalTo(itemIcon.snp.bottom)
// }
// itemTitle.text = titleArr[i]
// if(i == 0){
// itemIcon.textColor = selectColor
// itemTitle.textColor = selectColor
// }else{
// itemIcon.textColor = normalColor
// itemTitle.textColor = normalColor
// }
// tabIcons.append(itemIcon)
// tabTitles.append(itemTitle)
// item.tag = 1000 + i
// item.viewCallBack = { [unowned self] in
// self.selectedIndex = i
// for index in 0...self.tabIcons.count-1{
// let icon = self.tabIcons[index]
// let title = self.tabTitles[index]
// if(i == index){
// icon.textColor = selectColor
// title.textColor = selectColor
// }else{
// icon.textColor = normalColor
// title.textColor = normalColor
// }
// }
// }
// tab.addSubview(item)
// }
// }
//
//改变系统tabBar高度
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//确保代码执行一次
DispatchQueue.once {
self.tabBar.frame = CGRect(x: self.tabBar.frame.origin.x, y: self.view.frame.size.height - tabHeight, width: self.tabBar.frame.size.width, height: tabHeight)
self.tabBar.backgroundImage = UIImage.imageWithColor(color: UIColor.white, size: rect.size)
}
}
//
// @objc func tabTap(tap: UITapGestureRecognizer) {
//
// let selecIndex = tap.view?.tag ?? 1000 - 1000
// print(selecIndex)
//
// }
//
// func changeTabView(){
// self.tabBar.isHidden = true
// self.newTab?.isHidden = self.hidesBottomBarWhenPushed
// }
}
- IconFont
import UIKit
import CoreText
// 通过枚举获取你定义好的iconfont图标
public enum Icon: String {
case Home = "\u{e663}"
case Market = "\u{e60d}"
case ClassRoom = "\u{e617}"
case Collection = "\u{e67c}"
case Mine = "\u{e670}"
case Back = "\u{e65b}"
case Money = "\u{e61d}"
case AddFriend = "\u{e61a}"
case Order = "\u{e601}"
case Add = "\u{e6ec}"
case Search = "\u{e6a8}"
case Vegetables = "\u{e600}"
case Shopping = "\u{e64b}"
case Navgation = "\u{e625}"
case History = "\u{e6c7}"
case Notice = "\u{e67d}"
case Setting = "\u{e616}"
}
class IconFont: NSObject {
var code:String //标准解析格式 比如:"\u{a62b}"
var name:String //图标的名字.一般为中文,比如:设置
var descr:String! //图标作用和备注
var labelText:String! //可以直接赋值给UILabel,以系统字体大小为基准
var iconImage:UIImage!//生成一个一般的iconImge 如果需要其他大小的可以自己调整, 使用第二个初始化中代码段。
///初始化图标
/// - important : fontsize可通过外部font的size调整,而且必须设置UILabel的font,否则无法正常显示。比如:
/// - label.font = UIFont.init(name: "IconFont", size: UIFont.systemFontSize)
/// - parameter code: 标准解析格式,比如:"\u{a62b}"
/// - parameter name:图标的中文名
init(code:String, name:String) {
self.code = code
self.name = name
//为UILabel使用的做准备
let label = UILabel()
label.text = code
self.labelText = label.text
}
///初始化图标 ,图片可用
/// - important :图片大小由iconFont的fontSize自动计算决定。建议UIImageView大小参考打印值,这样的图片显示效果是最好的。
/// - parameter code: 标准解析格式,比如:"\u{a62b}"
/// - parameter name:图标的中文名
/// - parameter fontSize:图标(字体大小)
/// - parameter color:图标的颜色
convenience init(code:String, name:String, fontSize:CGFloat, color:UIColor){
self.init(code: code, name: name)
//计算文本rect
let nscode = code as NSString
let rect = nscode.boundingRect(with:CGSize(width: 0.0, height: 0.0) , options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : UIFont(name: "IconFont", size: fontSize)!], context: nil)
let size = rect.size
print("建议图片大小:\(size)") //建议UIImageView大小参考打印值
let label = UILabel(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
label.font = UIFont(name: "IconFont", size: fontSize)
label.textAlignment = .center
label.textColor = color
label.text = code
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
label.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
self.iconImage = image
}
///直接生成该图标的UIImage 对象
/// - important :图片大小由iconFont的fontSize自动计算决定。建议UIImageView大小参考打印值,这样的图片显示效果是最好的。
/// - parameter fontSize:图标(字体大小)
/// - parameter color:图标的颜色
func iconFontImage(fontSize:CGFloat, color:UIColor) -> UIImage {
//计算iconFont的宽高
let nscode = code as NSString
let rect = nscode.boundingRect(with:CGSize(width: 0.0, height: 0.0) , options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: fontSize)], context: nil)
let size = rect.size
print("建议图片大小:\(size)") //建议UIImageView大小参考打印值
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
label.font = UIFont(name: "IconFont", size: fontSize) //??为什么用IconFont和字体文件名一致(首字母大小写无所谓),但是不能换为其他的,哪怕你的iconFont的名字为其他的。
label.textAlignment = .center
label.text = code
label.textColor = color
label.layer.render(in: UIGraphicsGetCurrentContext()!) //??深入了解layer
let image = UIGraphicsGetImageFromCurrentImageContext()
return image!
}
}
//MARK: - 扩展UILable
extension UILabel{
///直接通过UILabel加载iconfont
/// - parameter iconfont: 图标的编码标准格式如:"\u{a626}"
convenience init(iconfont code:String, frame: CGRect ,fontSize:CGFloat) {
self.init(frame: frame)
self.text = code
self.font = UIFont(name: "IconFont", size: fontSize)
self.textAlignment = .center
}
}
//MARK: - 扩展UIImage
extension UIImage {
///直接通过生成UIImage
/// - parameter code: 图标的标准编码 如:"\u{a626}"
/// - parameter fontSize: 图标的字体大小,建议设置为UIImageView的高度,这样最合适,效果最好。
/// - parameter color: 图标的颜色。
convenience init(iconfont code:String,fontSize:CGFloat, color:UIColor){
let iconImage = IconFont(code: code, name: "", fontSize: fontSize, color: color).iconImage
let iconData:Data = iconImage!.pngData() ?? iconImage!.jpegData(compressionQuality: 1.0) ?? Data()
// UIImageJPEGRepresentation(iconImage!, 1.0
self.init(data: iconData)!
}
}
- hidesBottomBarWhenPushed问题, 第一个navgation页面设置何曾false
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.hidesBottomBarWhenPushed = true
}
public extension DispatchQueue {
private static var _onceTracker = [String]()
class func once(file: String = #file, function: String = #function, line: Int = #line, block:()->Void) {
let token = file + ":" + function + ":" + String(line)
once(token: token, block: block)
}
/**
Executes a block of code, associated with a unique token, only once. The code is thread safe and will
only execute the code once even in the presence of multithreaded calls.
- parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID
- parameter block: Block to execute once
*/
class func once(token: String, block:()->Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
}
网友评论