自定义带图标与文字的ToolbarItem,切换视图时遇标题不显示问题
解决UIToolbar自定义按钮不显示标题&动态切换的问题
兄弟,我懂你折腾一周的痛苦!咱们一步步来解决这个UIToolbar按钮不显示标题、以及视图切换时更新Toolbar的问题:
一、先修正你当前代码的核心问题
你的代码里有几个关键问题导致标题不显示:
- 没有给按钮设置图标与标题的间距,默认情况下两者会重叠挤压
- 直接替换
leftBarButton变量,但没有更新Toolbar的items数组,Storyboard里的旧按钮根本没被替换 - 没必要设置
semanticContentAttribute = .forceRightToLeft,除非你是RTL语言场景,反而会搞反图标和标题的位置
这里给你修正后的可复用代码:
class ViewController: UIViewController { @IBOutlet weak var toolbar: UIToolbar! // 保留Storyboard中绑定的BarButtonItem引用,后续替换它的customView @IBOutlet weak var leftBarButton: UIBarButtonItem! @IBOutlet weak var middleBarButton: UIBarButtonItem! @IBOutlet weak var rightBarButton: UIBarButtonItem! override func viewDidLoad() { super.viewDidLoad() setupCustomToolbarItems() } // 统一初始化Toolbar按钮 func setupCustomToolbarItems() { // 创建带图标+文字的Help按钮 let helpButton = createToolbarButton(imageName: "IconHelp", title: "Help", action: #selector(about)) // 替换原有leftBarButton的自定义视图 leftBarButton.customView = helpButton // 同理可以快速创建中间/右侧按钮 // let middleBtn = createToolbarButton(imageName: "IconHome", title: "Home", action: #selector(homeAction)) // middleBarButton.customView = middleBtn } // 封装按钮创建方法,复用性拉满 func createToolbarButton(imageName: String, title: String, action: Selector) -> UIButton { let button = UIButton(type: .system) // 设置图标和标题 button.setImage(UIImage(named: imageName), for: .normal) button.setTitle(title, for: .normal) // 关键:调整图标与标题的间距,避免重叠 button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0) // 图标右侧给标题留8pt空间 button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // 让按钮自适应大小 button.sizeToFit() button.addTarget(self, action: action, for: .touchUpInside) return button } @objc func about() { print("Help button tapped!") // 你的业务逻辑 } }
二、Storyboard的配套设置不能少
光改代码还不够,Storyboard里的配置也要跟上:
- 给UIToolbar添加BarButtonItem时,要插入
Flexible Space Bar Button Item来控制按钮的间距,让你的自定义按钮能正确排列 - 给每个需要替换的BarButtonItem设置足够的宽度(比如在Size Inspector里设为60pt),避免按钮被Toolbar压缩
- 不要在Storyboard里给BarButtonItem设置Image或Title,我们会用代码完全接管自定义视图
三、实现视图切换时的Toolbar动态变更
要让Toolbar随当前视图变化,你可以在每个ViewController的viewWillAppear方法里更新Toolbar内容:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 假设你的Toolbar是绑定在导航控制器上的,或者可以全局获取 guard let targetToolbar = self.navigationController?.toolbar else { return } // 创建当前视图需要的按钮 let backButton = createToolbarButton(imageName: "IconBack", title: "Back", action: #selector(goBack)) let saveButton = createToolbarButton(imageName: "IconSave", title: "Save", action: #selector(saveContent)) // 重新组装Toolbar的items数组 let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) targetToolbar.items = [backButton, flexibleSpace, saveButton] } @objc func goBack() { navigationController?.popViewController(animated: true) } @objc func saveContent() { // 保存逻辑 }
另外,关于你提到的TabBar疑问:其实TabBar也可以通过UITabBarControllerDelegate动态修改item样式,但它是全局底部导航,和你需要的“随当前视图灵活变更的Toolbar”场景不匹配,所以你选UIToolbar是完全正确的。
内容的提问来源于stack exchange,提问作者Aecasorg
相关产品推荐
相关产品推荐

