You need to enable JavaScript to run this app. 带居中UIButton的自定义TabBarController隐藏TabBar时按钮未同步隐藏的问题
优惠活动
大模型
产品
解决方案
定价
更多

带居中UIButton的自定义TabBarController隐藏TabBar时按钮未同步隐藏的问题

自定义TabBar中心按钮同步显隐 & 底部Toolbar位置适配

问题背景

开发实现了带居中凸起按钮的自定义TabBarController,在需要隐藏TabBar的二级页面,仅对系统TabBar本体做了隐藏处理,自定义的中心UIButton没有同步隐藏,悬浮在页面上破坏布局;同时二级页面展示底部Toolbar时,位置不符合预期,和TabBar隐藏后的布局逻辑不匹配。

效果参考

自定义TabBar正常显示效果
TabBar隐藏后的异常页面效果

现有实现代码

自定义TabBarController核心逻辑

let addButton = UIButton(frame: CGRect(x: 0, y: 0, width: 60, height: 60))

// MARK: - 生命周期
override func viewDidLoad() {
    super.viewDidLoad()
    self.delegate = self
    
    self.setupTabBar()
    self.setupAddButton()
}

// MARK: - 布局配置
private func setupTabBar() {
    let sectionTabNavigationController = createNavController(
        vc: MSMainCatalogVC(),
        title: NSLocalizedString("Catalog", comment: ""),
        image: UIImage(systemName: "text.justify"))
    
    let recentTabNavigationController = createNavController(
        vc: MSNotesTableVC(),
        title: NSLocalizedString("Recent", comment: ""),
        image: UIImage(systemName: "clock"))
    
    viewControllers = [recentTabNavigationController,
                       sectionTabNavigationController]
}

private func createNavController(vc: UIViewController,
                                 title: String,
                                 image: UIImage?) -> UINavigationController {
    let navController = UINavigationController(rootViewController: vc)
    navController.tabBarItem.title = title
    if let image = image {
        navController.tabBarItem.image = image
    }
    
    return navController
}

private func setupAddButton() {
        var addButtonFrame = addButton.frame
        addButtonFrame.origin.y = self.view.bounds.height - self.tabBar.bounds.height * 2
        addButtonFrame.origin.x = view.bounds.width/2 - addButtonFrame.size.width/2
        addButton.frame = addButtonFrame
        
        view.addSubview(addButton)
        
        addButton.setImage(UIImage(systemName: "plus"), for: .normal)
        addButton.backgroundColor = .systemGray6
        addButton.tintColor = UIColor.systemGray2
        addButton.layer.borderColor = UIColor.systemGray2.cgColor
        addButton.layer.borderWidth = 1
        addButton.layer.cornerRadius = 30
        
        addButton.addTarget(self, action: #selector(pressCenterButton(sender:)), for: .touchUpInside)
        
        view.layoutIfNeeded()
}

// MARK: - 交互事件
@objc private func pressCenterButton(sender: UIButton) {
    // 点击添加按钮弹出功能选择弹窗
    MSAddAlert.shared.show(for: self,
                           button1Title: NSLocalizedString("Make photo", comment: ""),
                           button2Title: NSLocalizedString("Select photo", comment: ""),
                           button3Title: NSLocalizedString("Make note", comment: ""),
                           button4Title: NSLocalizedString("Select file", comment: ""),
                           button1Action: self.makePhoto,
                           button2Action: self.addPhoto,
                           button3Action: self.goToAddNoteVC,
                           button4Action: nil)
}

private func goToAddNoteVC() {
    self.selectedViewController?.show(MSAddNoteVC(), sender: nil)
}

二级页面TabBar隐藏逻辑

private func setupBars() {
    self.navigationItem.title = self.title ?? NSLocalizedString("New note",
                                                                comment: "")
    self.tabBarController?.tabBar.alpha = 0
    self.navigationController?.setToolbarHidden(false,
                                                animated: true)
    if #available(iOS 14.0, *) {
        self.setToolbarItems([self.cancelButton,
                              UIBarButtonItem(systemItem: .flexibleSpace),
                              self.saveButton],
                             animated: true)
    } else {
        // 低版本iOS适配逻辑
    }
}

待解决问题

  1. 如何实现自定义中心添加按钮跟随TabBar的显示/隐藏逻辑同步切换状态,避免按钮悬浮残留
  2. 如何调整布局逻辑,让页面底部Toolbar放置在正确的位置,适配TabBar隐藏后的页面布局

解决方案

中心按钮与TabBar同步显隐

  • 调整按钮的添加层级:不要将中心按钮加在TabBarController的根视图上,改为添加为TabBar的子视图。这样按钮会和TabBar绑定显示层级,TabBar的alpha、isHidden属性变化时,子视图会同步生效,避免手动管理状态不同步

    对应修改:将view.addSubview(addButton)替换为tabBar.addSubview(addButton),同时将按钮的frame计算逻辑从基于整个controller视图bounds,改为基于tabBar的bounds计算凸起位置,保证按钮位置不受外层视图布局变化影响

  • 替换TabBar隐藏的实现方式:不要在二级页面手动设置tabBar.alpha = 0,统一使用系统提供的hidesBottomBarWhenPushed属性管理显隐:在需要隐藏TabBar的二级页面viewDidLoad方法中设置self.hidesBottomBarWhenPushed = true,该属性会自动触发TabBar及其所有子视图的隐藏动画,从根源上避免按钮残留的问题
  • 如果需要实现滚动时TabBar渐变的效果,可以在自定义TabBarController中监听TabBar的alpha值变化,同步设置addButton的alpha值,保证两个视图的透明度始终一致

修正底部Toolbar的位置

  • 移除二级页面手动设置tabBar.alpha = 0的代码后,Toolbar的位置会由iOS系统布局引擎自动计算:当hidesBottomBarWhenPushed生效、TabBar完全隐藏时,Toolbar会自动贴到安全区底部;当TabBar处于显示状态时,Toolbar会自动排布在TabBar上方,不需要手动调整frame
  • 排查是否存在手动修改安全区边距的代码,恢复导航控制器的默认布局逻辑:避免在二级页面手动修改self.additionalSafeAreaInsets的底部值,iOS会自动根据底部展示的TabBar、Toolbar高度,计算对应的内容安全区高度,不需要手动干预
  • 切换为hidesBottomBarWhenPushed管理TabBar显隐后,系统会自动处理转场过程中的布局动画,不会再出现Toolbar和中心按钮错位偏移的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 07:45:03