iOS 自定义TabBar Controller高度问题

Swift 复制代码
protocol CNCustomTabBarDelegate: NSObjectProtocol {
    func tabShouldSelectIndex(index: Int) -> Bool
    func tabBarDidClickAtIndex(index: Int)
    func centerButtonDidClick()
}

class CNCustomTabBar: UITabBar {
    
    static let HEIGHT: CGFloat = TAB_HEIGHT + CNScreen.safeAreaBottom

    // MARK: 不能设置小数, 否则tableView 分页滚动会有问题
    static let TAB_HEIGHT: CGFloat = 56
    
    weak var myDelegate: CNCustomTabBarDelegate?
    
    let TAG_NUM: Int = 100000
    
    var currentIndex: Int = 0 {
        willSet {
            if currentIndex >= 0 && currentIndex < CNTabItem.items.count {
                guard self.currentIndex != newValue else {
                    return
                }
                self.currentIndex = newValue
                updateTabBar()
            }
        }
    }
    
    var isDark: Bool {
        currentIndex == CNTabItem.hot.tabIndex
    }
    
    lazy var bgView: UIView = {
        let tmpView = UIView()
        tmpView.backgroundColor = .white
        return tmpView
    }()
    
    // MARK: 关键代码改变UITabBar 高度, 不重写sizeThatFits只是bgView 的高度改变
    override open func sizeThatFits(_ size: CGSize) -> CGSize {
        super.sizeThatFits(size)
        var sizeThatFits = super.sizeThatFits(size)
        sizeThatFits.height = CNCustomTabBar.HEIGHT
        return sizeThatFits
    }
    
    override init(frame: CGRect) {
        super.init(frame: .init(x: 0, y: 0, width: CNScreen.width, height: CNCustomTabBar.HEIGHT))
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        let cl: AnyClass? = NSClassFromString("UITabBarButton")
        if let cl {
            for item in subviews {
                if item.isKind(of: cl) {
                    item.removeFromSuperview()
                }
            }
        }
    }
    
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard !self.isHidden else {
            return nil
        }
        for i in 0..<CNTabItem.items.count {
            let btn = self.bgView.viewWithTag(TAG_NUM+i)
            if let btn,  btn.bounds.contains(btn.convert(point, from: self)) && btn.isHidden == false && btn.alpha == 1 {
                return btn
            }
        }
        return nil
    }
}

extension CNCustomTabBar {
    func setupUI() {
        bgView.frame = bounds
        bgView.roundCorners([.topLeft, .topRight], radius: 16)
        addSubview(bgView)
        //去除黑线
        let tabbarAppearance = self.standardAppearance
        tabbarAppearance.backgroundEffect = nil
        tabbarAppearance.backgroundImage = UIColor.clear.toImage()
        tabbarAppearance.shadowImage = UIColor.clear.toImage()
        self.standardAppearance = tabbarAppearance
        let itemW = CNScreen.width / CGFloat(CNTabItem.items.count)
        for (i, item) in CNTabItem.items.enumerated() {
            let tabBtn = setupTabButton(tabItem: item)
            tabBtn.addTarget(self, action: #selector(tabarBtnClick), for: .touchUpInside)
            bgView.addSubview(tabBtn)
            tabBtn.frame = CGRect(x: CGFloat(i) * itemW, y: 0, width: itemW, height: Self.TAB_HEIGHT)
        }
        updateTabBar()
    }
    
    @objc func tabarBtnClick(_ button: UIButton) {
        let index = button.tag - TAG_NUM
        let isShould = myDelegate?.tabShouldSelectIndex(index: index) ?? true
        if isShould {
            myDelegate?.tabBarDidClickAtIndex(index: index)
        } else {
            
        }
    }
    
    func updateTabBar() {
        bgView.backgroundColor = isDark ? .black : .white
        for (i, tabItem) in CNTabItem.items.enumerated() {
            let isSelected = currentIndex == i
            if let btn = self.bgView.viewWithTag(TAG_NUM+i) as? UIButton {
                var updateConfig = btn.configuration
                if isSelected {
                    updateConfig?.image = UIImage(named: tabItem.selImage)
                } else {
                    updateConfig?.image = UIImage(named: tabItem.norImage(isDark: isDark))
                }
                var titleColor = UIColor.hex("#A6ABB7")!
                if isDark && isSelected {
                    titleColor = UIColor.hex("#FFDA33")!
                } else if isDark {
                    titleColor = UIColor.hex("#CCCCCC")!
                } else if isSelected {
                    titleColor = UIColor.hex("#010101")!
                }
                let titleAttributes = AttributeContainer([
                    .font: UIFont.systemFont(ofSize: 10, weight: .medium),
                    .foregroundColor: titleColor
                ])
                let title = AttributedString(tabItem.title, attributes: titleAttributes)
                updateConfig?.attributedTitle = title
                btn.configuration = updateConfig
            }
        }
    }
    

    private func setupTabButton(tabItem: CNTabItem) -> UIButton {
        let button = UIButton()
        button.tag = TAG_NUM + tabItem.tabIndex
        var config = UIButton.Configuration.plain()
        config.baseBackgroundColor = .clear
        config.background.backgroundColor = .clear
        config.image = UIImage(named: tabItem.norImage(isDark: false))
        config.imagePlacement = .top
        config.imagePadding = 3
        let titleAttributes = AttributeContainer([
            .font: UIFont.systemFont(ofSize: 10, weight: .medium),
            .foregroundColor: UIColor.hex("#A6ABB7")!
        ])
        var title = AttributedString(tabItem.title, attributes: titleAttributes)
        config.attributedTitle = title
        button.configuration = config
        button.backgroundColor = .clear
        return button
    }
}

继承自UITabBar 自定义TabBar 时,遇到两个问题:

  1. 在 tabBarController 中 setValue(self.customTabBar, forKey: "tabBar") 设置self.customTabBar 后,tabBarController 的 viewControllers 高度 为屏幕高度,正常应该为 屏幕高度 - tabBar - 底部安全区高度,在设置tabBar.isTranslucent = false 后就莫名奇妙解决了。

  2. 项目中所有的高度使用了屏幕宽度等比缩放,即 h * w_scale,使用zfplayer 时, tableView 设置isPageEnable = true分页,如果cell 高度为小数,则会出现bug, 视频画面不能正常切换。这是因为自定义 TabBar 的高度一开始使用了等比缩放 56 * w_scale,修改为整数 56 后。恢复正常

相关推荐
开开心心就好4 天前
开源免费高速看图工具,支持漫画大图秒开
linux·运维·服务器·安全·ruby·symfony·1024程序员节
unable code7 天前
磁盘取证-Flying_High
网络安全·ctf·misc·1024程序员节·磁盘取证
unable code8 天前
磁盘取证-ColorfulDisk
网络安全·ctf·misc·1024程序员节·内存取证
unable code8 天前
磁盘取证-[第十章][10.1.2 磁盘取证方法]磁盘取证1
网络安全·ctf·misc·1024程序员节·内存取证
开开心心就好10 天前
免费抽奖工具支持批量导入+自定义主题
linux·运维·服务器·macos·pdf·phpstorm·1024程序员节
开开心心就好14 天前
卸载工具清理残留,检测垃圾颜色标识状态
linux·运维·服务器·python·安全·tornado·1024程序员节
子燕若水15 天前
Facebook reels 运营指南
1024程序员节
尘觉18 天前
创作 1024 天|把热爱写成长期主义
数据库·1024程序员节
写点什么呢19 天前
Word使用记录
word·1024程序员节
开开心心就好19 天前
内存清理工具点击清理,自动间隔自启
linux·运维·服务器·安全·硬件架构·材料工程·1024程序员节