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

新手求助:如何通过代码添加UIView替代导航栏(不使用Storyboard)

纯代码实现自定义导航栏替代NavigationBar

嘿,刚从Storyboard转纯代码布局的话,确实得调整下思路,我来帮你把这个自定义导航栏正确加到屏幕顶部,实现全屏宽度的效果~

首先看你提供的代码,有几个小问题需要修正,咱们一步步来:

1. 修正自定义ChatsNavBar的XIB加载逻辑

你现在的commonInit方法里重复添加了XIB里的子控件,其实XIB里的nameLabel、imageUser这些已经是navView的子视图了,不需要再单独addSubview到ChatsNavBar。正确的做法是把整个navView添加到ChatsNavBar,然后让它铺满整个父视图:

import UIKit

class ChatsNavBar: UIView {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var statusLabel: UILabel!
    @IBOutlet weak var imageUser: UIImageView!
    @IBOutlet weak var backButton: UIButton! {
        didSet {
            // 这里可以根据需求调整返回按钮的内边距,更贴合iOS原生风格
            backButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: -8, bottom: 0, right: 8)
        }
    }
    @IBOutlet weak var navView: UIView!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    private func commonInit() {
        let bundle = Bundle(for: ChatsNavBar.self)
        // 加载XIB,此时navView和内部控件已经关联到当前实例
        bundle.loadNibNamed("ChatsNavBar", owner: self, options: nil)
        
        // 禁用自动转换约束,改用Auto Layout精确控制布局
        navView.translatesAutoresizingMaskIntoConstraints = false
        // 把navView添加到当前ChatsNavBar作为子视图
        addSubview(navView)
        
        // 设置navView铺满整个ChatsNavBar
        NSLayoutConstraint.activate([
            navView.topAnchor.constraint(equalTo: self.topAnchor),
            navView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            navView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            navView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
        ])
    }
    
    @IBAction func backAction(_ sender: Any) {
        // 添加返回逻辑,比如回到上一个页面
        navigationController?.popViewController(animated: true)
    }
}

2. 在ChatsViewController中添加自定义导航栏并设置约束

接下来要在控制器里把这个自定义导航栏加到顶部,同时适配安全区(比如刘海屏的状态栏高度),实现全屏宽度:

class ChatsViewController: MessagesViewController {
    let user: MUser
    let chat: MChat
    // 声明自定义导航栏实例
    private let customNavBar = ChatsNavBar()

    init(user: MUser, chat: MChat) {
        self.user = user
        self.chat = chat
        super.init(nibName: nil, bundle: nil)
        // 隐藏系统默认导航栏,用自定义导航栏替代
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureMessageInputBar()
        setupCustomNavBar()
    }
    
    private func setupCustomNavBar() {
        // 禁用自动转换约束,开启Auto Layout
        customNavBar.translatesAutoresizingMaskIntoConstraints = false
        // 将自定义导航栏添加到控制器的view上
        view.addSubview(customNavBar)
        
        // 设置约束:顶部对齐安全区顶部,左右全屏,高度采用标准导航栏高度
        NSLayoutConstraint.activate([
            customNavBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            customNavBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            customNavBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            // 标准导航栏高度为44pt,若需要包含状态栏可调整为更大值
            customNavBar.heightAnchor.constraint(equalToConstant: 44)
        ])
        
        // 给自定义导航栏填充数据
        customNavBar.nameLabel.text = "\(chat.friendUsername) \(chat.friendUserSurname)"
        customNavBar.statusLabel.text = "在线" // 可替换为实际用户状态
        // customNavBar.imageUser.image = UIImage(named: user.avatarString) // 设置用户头像
    }
}

关键注意点

  • 隐藏系统导航栏:必须在控制器初始化时隐藏系统NavigationBar,避免和自定义导航栏重叠
  • Auto Layout约束:所有手动添加的视图都要设置translatesAutoresizingMaskIntoConstraints = false,通过约束明确位置和尺寸
  • 安全区适配:使用safeAreaLayoutGuide对齐顶部,确保在刘海屏、Notch屏上不会被状态栏遮挡
  • XIB加载逻辑:加载XIB后,只需把XIB的根视图(这里是navView)添加到自定义View,内部控件已通过XIB关联,无需重复添加

这样调整后,你的自定义导航栏就能正确显示在屏幕顶部,全屏宽度,完美替代系统NavigationBar啦~

内容的提问来源于stack exchange,提问作者Eugene

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:12:45