You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将UITabBarItem中的图片与标题文本独立定位?

解决UITabBarItem选中文本加粗导致图片偏移的问题

嘿,这个场景我太熟了!默认UITabBarItem的布局逻辑是把图片和标题当成一个整体来排版,文本加粗后宽度变大,就会拉扯着图片一起偏移,确实挺烦的。要让这两个元素定位完全独立,最靠谱的是自定义UITabBarItem的内容视图,让我们完全掌控它们的布局约束,下面给你详细说两种方案:

方案一:自定义TabBarItem视图(推荐,稳定可控)

直接抛弃系统默认的UITabBarItem布局,自己创建一个包含图片和标签的UIView,把它设置为UITabBarItem的customView。这样图片和标签的约束都由我们定义,文本怎么变都不会影响图片位置。

第一步:创建自定义视图类

class CustomTabBarItemView: UIView {
    private let iconImageView = UIImageView()
    private let titleLabel = UILabel()
    
    // 初始化方法
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupSubviewsAndConstraints()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupSubviewsAndConstraints()
    }
    
    // 配置子视图和约束
    private func setupSubviewsAndConstraints() {
        // 配置图片视图
        iconImageView.contentMode = .scaleAspectFit
        iconImageView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(iconImageView)
        
        // 配置标题标签
        titleLabel.textAlignment = .center
        titleLabel.font = UIFont.systemFont(ofSize: 10)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        addSubview(titleLabel)
        
        // 设置核心约束:图片和标签都绑定到父视图的中心X,互相之间只保留固定间距
        NSLayoutConstraint.activate([
            // 图片居中,底部和标签顶部间距固定
            iconImageView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            iconImageView.bottomAnchor.constraint(equalTo: titleLabel.topAnchor, constant: -4),
            iconImageView.widthAnchor.constraint(equalToConstant: 24),
            iconImageView.heightAnchor.constraint(equalToConstant: 24),
            
            // 标签居中,底部贴父视图底部
            titleLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -2)
        ])
    }
    
    // 对外暴露配置方法,设置图片、标题和选中状态
    func setup(with image: UIImage?, title: String?, isSelected: Bool) {
        iconImageView.image = image?.withRenderingMode(.alwaysTemplate)
        titleLabel.text = title
        
        // 选中时加粗文本,同时调整颜色
        let selectedTint = UIColor.systemBlue
        let normalTint = UIColor.gray
        
        titleLabel.font = isSelected ? UIFont.boldSystemFont(ofSize: 10) : UIFont.systemFont(ofSize: 10)
        iconImageView.tintColor = isSelected ? selectedTint : normalTint
        titleLabel.textColor = isSelected ? selectedTint : normalTint
    }
}

第二步:在TabBarController中使用自定义视图

class MainTabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTabBarItems()
        // 监听tab选中事件,更新视图状态
        self.delegate = self
    }
    
    private func setupTabBarItems() {
        // 示例:创建第一个Tab的视图控制器和自定义TabItem
        let homeVC = HomeViewController()
        let homeTabView = CustomTabBarItemView()
        homeTabView.setup(with: UIImage(named: "home_icon"), title: "首页", isSelected: true)
        homeVC.tabBarItem.customView = homeTabView
        
        // 重复上述步骤创建其他4个Tab...
        let discoverVC = DiscoverViewController()
        let discoverTabView = CustomTabBarItemView()
        discoverTabView.setup(with: UIImage(named: "discover_icon"), title: "发现", isSelected: false)
        discoverVC.tabBarItem.customView = discoverTabView
        
        // 把所有VC添加到TabBarController
        self.viewControllers = [homeVC, discoverVC, /* 剩下3个VC */]
    }
}

// 实现TabBarControllerDelegate,处理选中状态切换
extension MainTabBarController: UITabBarControllerDelegate {
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        guard let tabItems = tabBarController.tabBar.items else { return }
        
        // 遍历所有TabItem,更新自定义视图的选中状态
        for (index, item) in tabItems.enumerated() {
            guard let customTabView = item.customView as? CustomTabBarItemView else { continue }
            let isSelected = index == tabBarController.selectedIndex
            customTabView.setup(with: item.image, title: item.title, isSelected: isSelected)
        }
    }
}

这样设置后,不管标题是否加粗,图片始终保持在父视图的中心位置,完全不受文本宽度变化的影响。

方案二:修改系统UITabBarItem内部约束(hack方式,不推荐)

如果你不想自定义视图,也可以通过KVC获取系统UITabBarItem内部的图片和标签视图,强制修改它们的约束,让两者都绑定到父视图中心。不过这个方法依赖苹果的私有API结构,后续系统更新可能失效,谨慎使用:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    for item in tabBar.items ?? [] {
        guard let containerView = item.value(forKey: "view") as? UIView else { continue }
        
        for subview in containerView.subviews {
            if subview is UIImageView {
                // 固定图片的中心X约束
                subview.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
            } else if subview is UILabel {
                // 固定标签的中心X约束
                subview.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
            }
        }
    }
}

总结

优先选择自定义视图方案,它不仅解决了图片偏移的问题,还能让你完全自定义TabBarItem的样式(比如调整图片大小、文本字号、间距等),扩展性极强,而且完全符合苹果的开发规范,不会有后续版本兼容问题。

内容的提问来源于stack exchange,提问作者spencer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:54:25