iOS 11自定义导航栏后无法修改右侧BarButtonItem高度怎么办?
哈哈,这个坑我之前踩过!iOS 11之后导航栏的布局逻辑改了,UIBarButtonItem被塞进UIBarButtonStackView里,默认就被卡着44pt的高度,想突破确实得费点功夫。给你几个靠谱的解决方案:
1. 先确保自定义导航栏的布局是对的
你自定义导航栏高度的时候,别只改frame,得让导航栏内部的内容容器跟着扩展,不然按钮再大也会被容器裁切。可以自定义UINavigationBar子类来实现:
class CustomNavBar: UINavigationBar { override func sizeThatFits(_ size: CGSize) -> CGSize { // 这里设你想要的导航栏高度,比如60pt return CGSize(width: UIScreen.main.bounds.width, height: 60) } override func layoutSubviews() { super.layoutSubviews() // 找到导航栏的内容容器,让它铺满整个导航栏 for subview in subviews { if NSStringFromClass(subview.classForCoder) == "_UINavigationBarContentView" { subview.frame = bounds } } } }
把这个自定义导航栏给你的导航控制器用,这样内部的栈视图就有足够的空间了。
直接改系统UIBarButtonItem的约束基本没用,最稳妥的方式是自己做个UIButton,再包装成UIBarButtonItem,这样大小完全由你控制:
private func makeCustomRightButton() -> UIBarButtonItem { let customBtn = UIButton(type: .custom) customBtn.setImage(UIImage(named: "your-icon"), for: .normal) customBtn.addTarget(self, action: #selector(rightBtnTapped), for: .touchUpInside) // 这里直接设你想要的宽高,比如50pt customBtn.widthAnchor.constraint(equalToConstant: 50).isActive = true customBtn.heightAnchor.constraint(equalToConstant: 50).isActive = true return UIBarButtonItem(customView: customBtn) } @objc private func rightBtnTapped() { // 按钮点击逻辑 }
然后把这个按钮设置到导航栏:
navigationItem.rightBarButtonItem = makeCustomRightButton()
这个方法完全不依赖私有API,系统版本更新也不怕出问题。
3. 暴力修改栈视图约束(不推荐)
如果你非要用系统的UIBarButtonItem,可以尝试遍历导航栏子视图找到UIBarButtonStackView,然后修改它的约束。但这个方法依赖私有类名,苹果哪天改了就失效了,谨慎用:
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 递归查找UIBarButtonStackView func findStackView(in view: UIView) -> UIStackView? { for subview in view.subviews { if subview is UIStackView && subview.classForCoder.description().contains("UIBarButtonStackView") { return subview as? UIStackView } if let stack = findStackView(in: subview) { return stack } } return nil } guard let stackView = findStackView(in: navigationController!.navigationBar) else { return } // 移除原有高度约束 stackView.constraints.forEach { if $0.firstAttribute == .height { $0.isActive = false } } // 设置新高度 stackView.heightAnchor.constraint(equalToConstant: 50).isActive = true stackView.layoutIfNeeded() }
总结
优先选第二种方法,自定义按钮包装成UIBarButtonItem,既安全又灵活。第一种是基础,确保导航栏的容器能容纳下更大的按钮。第三种实在没办法再用,风险较高。
内容的提问来源于stack exchange,提问作者Lucy
相关产品推荐
相关产品推荐

