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

相关推荐
u0103055272 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u0103055272 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝4 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u0103055274 天前
Java图像处理实战指南
人工智能·1024程序员节
u0103055275 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u0103055277 天前
Java实用类应用精讲
人工智能·1024程序员节
u0103055277 天前
Java I/O核心操作实战
人工智能·1024程序员节
u0103055278 天前
ArrayList操作详解与实战应用
人工智能·1024程序员节
u0103055279 天前
Java模块化编程实战指南
人工智能·笔记·1024程序员节
u01030552710 天前
使用BufferedReader读取控制台输入
人工智能·1024程序员节