如何修改UIBarButtonItem的顶部约束?自定义导航栏适配问题
代码问题修正
你当前的代码存在两处关键错误:
customNavigationItem = UIBarButtonItem.init(...)语法错误,应为导航项设置leftBarButtonItem属性- 直接向导航控制器View添加自定义导航栏的方式不符合iOS导航控制器规范,易引发布局冲突
解决方案:容器视图包裹按钮实现偏移
要实现按钮顶部偏移12的效果,无法直接修改UIBarButtonItem的约束,需用容器视图包裹按钮,通过容器与按钮的约束控制偏移。以下是完整修正代码:
1. 自定义导航控制器代码
class CustomNavigationViewController: UINavigationController { override func viewDidLoad() { super.viewDidLoad() // 让导航控制器使用自定义导航栏类 navigationBar.isHidden = true let customNavBar = CustomNavigationBar(frame: CGRect( x: 0, y: view.safeAreaInsets.top, width: UIScreen.main.bounds.width, height: 68 )) view.addSubview(customNavBar) // 创建自定义按钮 let customButton = UIButton(type: .custom) customButton.setImage(UIImage(named: "iOS2"), for: .normal) customButton.frame = CGRect(x: 0, y: 0, width: 44, height: 44) // 用容器视图包裹按钮,控制顶部偏移 let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44)) containerView.addSubview(customButton) customButton.translatesAutoresizingMaskIntoConstraints = false // 设置按钮顶部偏移12,其余方向对齐容器 NSLayoutConstraint.activate([ customButton.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 12), customButton.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), customButton.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), customButton.bottomAnchor.constraint(equalTo: containerView.bottomAnchor) ]) // 配置导航项并绑定按钮 let navItem = UINavigationItem() navItem.leftBarButtonItem = UIBarButtonItem(customView: containerView) customNavBar.items = [navItem] } // 更规范的自定义导航栏方式:重写导航栏类 override class var navigationBarClass: AnyClass { return CustomNavigationBar.self } }
2. 自定义导航栏代码(适配高度)
class CustomNavigationBar: UINavigationBar { private let targetHeight: CGFloat = 68 override init(frame: CGRect) { super.init(frame: frame) commonSetup() } required init?(coder: NSCoder) { super.init(coder: coder) commonSetup() } private func commonSetup() { backgroundColor = .white } // 重写该方法设定导航栏高度 override func sizeThatFits(_ size: CGSize) -> CGSize { return CGSize(width: UIScreen.main.bounds.width, height: targetHeight) } // 适配安全区域,确保导航栏位置正确 override func layoutSubviews() { super.layoutSubviews() guard let window = UIApplication.shared.windows.first else { return } frame = CGRect( x: 0, y: window.safeAreaInsets.top, width: frame.width, height: targetHeight ) } }
核心逻辑说明
- UIBarButtonItem会对其customView进行默认布局,直接修改按钮约束无法生效,通过容器视图中转,可自定义按钮在容器内的位置,从而实现顶部偏移。
- 重写
navigationBarClass是自定义导航栏的标准方式,比手动添加子视图更稳定,能避免布局层级冲突。
内容的提问来源于stack exchange,提问作者user25462420
相关产品推荐
相关产品推荐

