iOS导航栏titleView按钮失效与无法居中的兼容问题如何解决
问题原因
UINavigationBar对titleView的默认布局规则是:先预留出左右导航按钮的位置,再将titleView放在两侧按钮之间的剩余空间内做居中对齐,同时titleView的交互范围默认严格匹配自身的intrinsicContentSize尺寸。
- 最开始未修改intrinsicContentSize时,titleView尺寸刚好贴合内部label和按钮的大小,因为整体宽度小,视觉上刚好和整个导航栏的中心对齐,但这时候系统给titleView分配的实际布局/交互区域被压缩,按钮超出可响应区域的部分收不到点击事件,所以点不动。
- 添加返回
UIView.layoutFittingExpandedSize的代码后,相当于告诉系统这个titleView要占满两侧按钮之间的所有可用宽度,这时候titleView被拉伸到撑满剩余空间,自然就只能在剩余空间内居中,出现偏移,没法实现相对于整个导航栏全局居中的效果。
实现方案
不需要修改titleView的intrinsicContentSize,按以下步骤调整即可同时满足两个需求:
- 自定义UIView子类作为titleView的容器,内部用Auto Layout正常摆放label和图片按钮,让容器靠内部内容自然撑开尺寸,不要做额外的尺寸拉伸。
- 重写容器view的点击判定方法,扩大交互响应范围,解决按钮点击无响应的问题,代码如下:
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { for subview in subviews where subview.isUserInteractionEnabled && !subview.isHidden { let targetPoint = convert(point, to: subview) if subview.point(inside: targetPoint, with: event) { return true } } return super.point(inside: point, with: event) }
- 在对应页面的
viewDidLayoutSubviews生命周期里,手动校正titleView的位置,让它相对于整个导航栏居中:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() guard let titleView = navigationItem.titleView, let navBar = navigationController?.navigationBar else { return } titleView.center.x = navBar.bounds.midX }
注意事项
如果titleView内部内容总宽度过大,要提前给label设置最大宽度限制,避免titleView和左右导航按钮出现大面积重叠,影响导航按钮的正常点击。
内容的提问来源于stack exchange,提问作者Ginso
相关产品推荐
相关产品推荐

