如何修复使用TabBar时屏幕顶部出现的多余空白问题?
问题:影片目录App TabBar顶部出现多余空白
我正在开发一款影片目录App,使用TabBar时遇到UI问题:屏幕顶部出现了多余空白。相关Swift代码如下:
TabbarViewController代码
import UIKit class TabbarViewController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() navigationItem.setHidesBackButton(true, animated: false) let vc1 = ListMovieViewController() let vc2 = SearchViewController() vc1.title = "List" vc2.title = "Search" vc1.navigationItem.largeTitleDisplayMode = .always vc2.navigationItem.largeTitleDisplayMode = .always let nav1 = UINavigationController(rootViewController: vc1) let nav2 = UINavigationController(rootViewController: vc2) nav1.tabBarItem = UITabBarItem(title: "List", image: UIImage(systemName: "film"), tag: 1) nav2.tabBarItem = UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass"), tag: 1) nav1.navigationBar.prefersLargeTitles = true nav2.navigationBar.prefersLargeTitles = true setViewControllers([nav1,nav2], animated: false) } }
ListMovieViewController代码
import UIKit class ListMovieViewController: UIViewController { private let tableView: UITableView = { let tableVw = UITableView() tableVw.register(FilmCell.self, forCellReuseIdentifier: "FilmCell") return tableVw }() private var filmViewModels: FilmViewModels = FilmViewModels() override func viewDidLoad() { super.viewDidLoad() //NavBar title = "Catalog" view.backgroundColor = .systemBackground navigationController?.navigationBar.prefersLargeTitles = true SetUp() } private func SetUp(){ view.addSubview(tableView) tableView.delegate = self tableView.dataSource = self tableView.frame = view.bounds } }
ListMovieViewController扩展代码
extension ListMovieViewController: UITableViewDelegate, UITableViewDataSource{ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return filmViewModels.getLength() } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "FilmCell", for: indexPath) as! FilmCell let film = filmViewModels.films[indexPath.row] let imageUrl = film.imageUrl cell.filmImageView.downloaded(from: imageUrl) cell.titleLabel.text = film.title cell.directorLable.text = "Director by \(film.director)" return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 130 } }
当前界面截图

解决方案
问题根源
代码存在双层导航栏嵌套的问题:TabbarViewController本身被嵌套在外部UINavigationController中(从navigationItem.setHidesBackButton(true)可判断),同时每个Tab页的子视图控制器又各自创建了独立的UINavigationController,导致顶部出现冗余空白区域。此外,ListMovieViewController中直接设置tableView.frame = view.bounds未考虑安全区域和导航栏的布局影响,加剧了布局异常。
修复步骤
1. 移除外层导航栏嵌套(推荐方案)
如果App不需要给TabbarViewController添加外层导航栏,直接将其设置为App的根控制器:
// 在SceneDelegate或AppDelegate中修改根控制器配置 window?.rootViewController = TabbarViewController()
2. 若必须保留外层导航栏,隐藏外层导航栏
在TabbarViewController的viewDidLoad中添加代码隐藏外层导航栏:
override func viewDidLoad() { super.viewDidLoad() navigationItem.setHidesBackButton(true, animated: false) // 添加此行隐藏外层导航栏 navigationController?.navigationBar.isHidden = true // 其余原有代码保持不变 }
3. 优化TableView布局
将ListMovieViewController中SetUp方法的tableView.frame = view.bounds替换为自动适配的布局方式,确保TableView正确适配导航栏和安全区域:
private func SetUp(){ view.addSubview(tableView) tableView.delegate = self tableView.dataSource = self // 使用AutoLayout约束(推荐) tableView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: view.topAnchor), tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) // 或者使用自动调整掩码 // tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight] }
4. 统一标题设置
移除ListMovieViewController中重复的标题设置,保持与TabbarViewController中的标题一致:
// 删除ListMovieViewController里的此行代码 // title = "Catalog"
验证修复
完成上述修改后,顶部的多余空白会消失,导航栏与TableView的布局将正确适配屏幕。
内容的提问来源于stack exchange,提问作者Shillwi2593
相关产品推荐
相关产品推荐

