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

Swift中UIButton创建的UIBarButtonItem布局异常:工具栏元素重叠求助

解决UIToolbar自定义按钮被中间元素遮挡的问题

我之前也踩过UIToolbar自定义按钮布局的坑,你的问题主要出在硬编码按钮frame和空间项使用不当这两点上——UIToolbar的布局逻辑和普通View不一样,手动强设宽度很容易导致元素重叠遮挡,下面给你针对性的解决方案:

问题根源分析

  • 你给中间的titleButton硬编码了width: self.view.frame.width - 180,这个宽度会直接挤压左右按钮的可用空间,导致按钮被遮挡;
  • 使用fixedSpace的方式不对,应该用flexibleSpace让中间元素自动填充剩余空间,而不是固定宽度的间隔;
  • contentEdgeInsets用了负值,反而会让按钮的点击区域或显示范围超出预期,加重遮挡问题。

修改后的完整代码

let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.sizeToFit()

// 中间标题按钮:移除硬编码frame,用AutoLayout控制宽度范围
let titleButton = UIButton(type: .custom)
titleButton.titleLabel?.numberOfLines = 0
titleButton.setTitle(self.toolBarLabelString, for: .normal)
titleButton.setTitleColor(.darkGray, for: .normal)
titleButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    titleButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 100), // 保证标题有最小显示空间
    titleButton.widthAnchor.constraint(lessThanOrEqualToConstant: self.view.frame.width - 120) // 给左右按钮留足空间
])
titleButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) // 用正值内边距调整文本位置

// 右侧Done按钮:移除硬编码frame,优化内边距
let doneButton = UIButton(type: .custom)
doneButton.setTitle("Done", for: .normal)
doneButton.setTitleColor(.green, for: .normal)
doneButton.addTarget(self, action: #selector(CreateRecipeViewController.donePicker), for: .touchUpInside)
doneButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)

// 左侧Cancel按钮:移除硬编码frame,优化内边距
let cancelButton = UIButton(type: .custom)
cancelButton.setTitle("Cancel", for: .normal)
cancelButton.setTitleColor(.red, for: .normal)
cancelButton.addTarget(self, action: #selector(CreateRecipeViewController.cancelPicker), for: .touchUpInside)
cancelButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)

// 包装成BarButtonItem,用弹性空间分配布局
let titleBarButton = UIBarButtonItem(customView: titleButton)
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelBarButton = UIBarButtonItem(customView: cancelButton)
let doneBarButton = UIBarButtonItem(customView: doneButton)

// 重新设置items:左右按钮+弹性空间+中间标题,自动适配布局
toolBar.setItems([cancelBarButton, flexibleSpace, titleBarButton, flexibleSpace, doneBarButton], animated: false)
toolBar.isUserInteractionEnabled = true

关键修改点说明

  • 移除所有自定义按钮的frame设置,改用AutoLayout约束控制标题按钮的宽度范围,避免挤压左右按钮;
  • 把fixedSpace换成flexibleSpace,让UIToolbar自动分配空间,左右按钮会自动贴边,中间标题填充剩余区域;
  • 把contentEdgeInsets的负值改成正值,合理调整按钮文本的内边距,保证点击区域和显示范围正常;
  • 给标题按钮设置最小/最大宽度,既保证标题能正常显示,又不会占用过多空间导致左右按钮被遮挡。

这样调整后,三个元素就能正常布局,左右按钮不会再被中间元素遮挡啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:37:32