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

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
            }
        }
    }
}

把这个自定义导航栏给你的导航控制器用,这样内部的栈视图就有足够的空间了。

2. 自定义按钮来替代系统UIBarButtonItem

直接改系统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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:34:36