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 后。恢复正常

相关推荐
Kent Gu7 小时前
Qutatus读取FPGA内部程序
其他·1024程序员节
蜗牛沐雨7 小时前
详解C++中的字符串流
c++·1024程序员节
蜗牛沐雨7 小时前
详解C++中的流
c++·1024程序员节
重生之我是Java开发战士7 小时前
【Java EE】了解Spring Web MVC:请求与响应的全过程
spring boot·spring·java-ee·1024程序员节
懒羊羊不懒@7 小时前
Java—枚举类
java·开发语言·1024程序员节
zerolala7 小时前
Java容器常用方法
java·1024程序员节
彩云回7 小时前
堆叠泛化(Stacking)
人工智能·机器学习·1024程序员节
Evand J7 小时前
【MATLAB例程】自适应渐消卡尔曼滤波,背景为二维雷达目标跟踪,基于扩展卡尔曼(EKF)|附完整代码的下载链接
开发语言·matlab·目标跟踪·1024程序员节
zl_dfq8 小时前
Linux基础开发工具 之 【yum、vim、gcc/g++】
linux·1024程序员节