UINavigationItem左右BarButton在iPhone6+上不显示问题求助
问题排查与解决方案
从你的描述和代码来看,问题出在直接向UINavigationBar添加自定义子视图的操作上,这在iPhone 6+这类大屏设备上导致自定义视图覆盖了左右BarButton的显示区域——按钮实际上存在(所以能响应点击),但被上层的自定义viewLabel挡住了,因此看不见。
核心问题分析
你在viewDidLoad里直接执行了:
self.navigationController?.navigationBar.addSubview(viewLabel)
这种做法会绕过导航栏自身的布局系统,你手动计算的frameLabelURLTitle和frameLabelURL在iPhone 6+上的宽度可能超出了标题区域的合理范围,挤占了左右BarButton的空间,导致按钮被遮挡。而iPhone 5s(小屏)和iPhone X(有刘海的特殊布局)刚好没有触发这个遮挡问题。
修复方案:用navigationItem.titleView替代直接添加子视图
导航栏的标题区域应该通过navigationItem.titleView来设置自定义视图,系统会自动处理不同屏幕尺寸下的布局,避免和BarButton冲突。具体修改步骤如下:
重构自定义标题视图的创建逻辑
把创建viewLabel、labelTitleURL、labelURL的代码改成赋值给navigationItem.titleView,而不是添加到navigationBar:override func viewDidLoad() { super.viewDidLoad() webView.delegate = self loadWeb() // 右侧按钮保持不变 let button = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(share)) button.tintColor = .white self.navigationItem.rightBarButtonItem = button // 重构自定义标题视图:使用navigationItem.titleView let viewLabel = UIView() viewLabel.translatesAutoresizingMaskIntoConstraints = false labelTitleURL = UILabel() labelTitleURL.textColor = .white labelTitleURL.font = UIFont.systemFont(ofSize: 15) // 调整字号更适配 labelTitleURL.translatesAutoresizingMaskIntoConstraints = false labelURL = UILabel() labelURL.textColor = .white labelURL.font = UIFont.systemFont(ofSize: 13) labelURL.translatesAutoresizingMaskIntoConstraints = false viewLabel.addSubview(labelTitleURL) viewLabel.addSubview(labelURL) // 用AutoLayout替代固定frame,适配所有屏幕 NSLayoutConstraint.activate([ labelTitleURL.topAnchor.constraint(equalTo: viewLabel.topAnchor), labelTitleURL.leadingAnchor.constraint(equalTo: viewLabel.leadingAnchor), labelTitleURL.trailingAnchor.constraint(equalTo: viewLabel.trailingAnchor), labelURL.topAnchor.constraint(equalTo: labelTitleURL.bottomAnchor, constant: 2), labelURL.leadingAnchor.constraint(equalTo: viewLabel.leadingAnchor), labelURL.trailingAnchor.constraint(equalTo: viewLabel.trailingAnchor), labelURL.bottomAnchor.constraint(equalTo: viewLabel.bottomAnchor) ]) // 赋值给titleView,系统自动处理布局 self.navigationItem.titleView = viewLabel // 其他原有代码保持不变 loadingLabel.text = "loadingWeb".localized() loadingLabel.sizeToFit() self.navigationController?.isNavigationBarHidden = true self.placeHolderView.layer.insertSublayer(initGradient(bounds: self.view.bounds, isHorizontal: false), at: 0) self.loadingGifImageView.image = UIImage.gif(asset: "01-GIF_LOGO") }简化左侧按钮的设置逻辑
在webViewDidFinishLoad里你重复设置了多次leftBarButtonItem,可以简化为:func webViewDidFinishLoad(_ webView: UIWebView) { self.placeHolderView.isHidden = true self.navigationController?.isNavigationBarHidden = false labelTitleURL.text = webView.stringByEvaluatingJavaScript(from: "document.title") labelURL.text = webView.request?.url?.absoluteString.components(separatedBy: "/")[2] // 重置左侧按钮 if let url = webView.request?.url, !url.absoluteString.contains("/blog/") { let newBackButton = UIBarButtonItem(image: UIImage(named: "bt_close")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(back)) self.navigationItem.leftBarButtonItem = newBackButton } else { self.navigationItem.leftBarButtonItem = nil } // 不需要设置backBarButtonItem,这是给下一个页面返回按钮用的 }
额外检查点
- 确认
bt_close图片在iPhone 6+的资源包里存在,避免因图片缺失导致按钮看不见(不过你说能点击,所以这个可能性较低)。 - 避免直接修改
UINavigationBar的子视图,苹果官方推荐通过navigationItem的属性来定制导航栏元素,这样能保证在所有设备上的布局一致性。
按照这个方案修改后,iPhone 6+上的BarButton应该能正常显示了。
内容的提问来源于stack exchange,提问作者Xavier Tordera
相关产品推荐
相关产品推荐

