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

相关推荐
开开心心就好2 小时前
用户推荐的文件解锁与强制操作工具
安全·智能手机·pdf·scala·音视频·symfony·1024程序员节
liguojun20255 天前
软硬一体智慧场馆系统推荐——助力场馆数字化高效升级
java·大数据·人工智能·物联网·1024程序员节
开开心心就好17 天前
吾爱大佬原创的文件时间修改工具
安全·智能手机·pdf·电脑·智能音箱·智能手表·1024程序员节
开开心心就好22 天前
近200个工具的电脑故障修复合集
安全·智能手机·pdf·电脑·consul·memcache·1024程序员节
数据皮皮侠AI24 天前
中国城市可再生能源数据集(2005-2021)|顶刊 Sci Data 11 种能源面板
大数据·人工智能·笔记·能源·1024程序员节
计算机毕业论文辅导1 个月前
物联网实战:基于MQTT协议的智能家居数据传输系统设计与实现
1024程序员节
开开心心就好1 个月前
支持批量处理的视频分割工具推荐
安全·智能手机·rust·pdf·电脑·1024程序员节·lavarel
liuyao_xianhui1 个月前
Linux开发工具结尾 _make
linux·运维·服务器·数据结构·哈希算法·宽度优先·1024程序员节
学传打活1 个月前
【边打字.边学昆仑正义文化】_21_爱的结晶(1)
微信公众平台·1024程序员节·汉字·昆仑正义文化
数据皮皮侠AI1 个月前
顶刊同款!中国地级市风灾风险与损失数据集(2000-2022)|灾害 / 环境 / 经济研究必备
大数据·人工智能·笔记·能源·1024程序员节