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
相关产品推荐
相关产品推荐

