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

如何修复使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 04:25:05