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

Swift中UITabBar上方CollectionView触摸失效问题求助

UITabBar上方CollectionView无法响应触摸的问题修复

问题描述

在UITabBar上方添加了包含CollectionView的quickAccessView,但该CollectionView无法响应触摸操作。

原始实现代码

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    self.tabBar.bringSubviewToFront(quickAccessView)
}

private func setupQuickAccessView(){
    print("this is tabBar's height", self.tabBar.frame.size.height)
    self.tabBar.frame.size.height = 150
    print("this is new tabBar's height", self.tabBar.frame.size.height)
    self.tabBar.addSubview(quickAccessView)
    quickAccessView.clipsToBounds = true
}

private func addQuickAccessViewConstraints(){
    quickAccessView.snp.makeConstraints { make in
        make.right.left.equalTo(self.tabBar.safeAreaLayoutGuide)
        make.height.equalTo(76)
        make.bottom.equalTo(self.tabBar.snp.bottom).offset(-80)
    }
}

修改后的代码及存在的问题

UITabBarController部分

强制将tabBar转换为QuickAccessSupportedTabBar时崩溃,且viewDidAppear中错误修改了主视图frame:

final class MainTabBarController: UITabBarController {
   private lazy var quickAccessView: QuickAccessView = .fromNib()
    var quickAccessSupportedTabBar: QuickAccessSupportedTabBar {
        self.tabBar as! QuickAccessSupportedTabBar // 此处崩溃
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tabBar.backgroundColor = .white
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.view.frame = self.quickAccessView.bounds // 错误设置
        setupUI()
    }
}

extension MainTabBarController{
    private func setupUI(){
        setupQuickAcessView()
        addQuickAcessViewConstraints()
    }
}

// MARK: - Setting Up Quick Access view
extension MainTabBarController {
    private func setupQuickAcessView(){
        self.quickAccessSupportedTabBar.addSubview(quickAccessView)
    }
    
    private func addQuickAcessViewConstraints(){
        quickAccessView.snp.makeConstraints { make in
            make.left.right.equalTo(self.quickAccessSupportedTabBar.safeAreaLayoutGuide)
            make.height.equalTo(66)
            make.bottom.equalTo(self.quickAccessSupportedTabBar.snp.top)
        }
    }
}

自定义UITabBar部分

无法访问quickAccessView,坐标转换逻辑有误:

class QuickAccessSupportedTabBar: UITabBar {
    override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if !quickAccessView.isHidden { // 无法访问quickAccessView
            let targetPoint = quickAccessView.convert(point, from: self) // 坐标转换方向错误
            
            if quickAccessView.bounds.contains(targetPoint) {
                return quickAccessView.hitTest(targetPoint, with: event)
            }
        }
        return super.hitTest(point, with: event)
    }
}

解决方案

1. 修复TabBar类型转换崩溃

确保TabBarController的tabBar确实是自定义的QuickAccessSupportedTabBar类型:

  • 代码初始化方式:在viewDidLoad中替换默认TabBar
override func viewDidLoad() {
    super.viewDidLoad()
    self.tabBar = QuickAccessSupportedTabBar()
    self.tabBar.backgroundColor = .white
}
  • Storyboard方式:选中TabBar组件,在Identity Inspector中将Class设置为QuickAccessSupportedTabBar。

2. 让自定义TabBar能访问quickAccessView并修正触摸检测逻辑

修改自定义TabBar,添加属性持有quickAccessView引用,并修正坐标转换:

class QuickAccessSupportedTabBar: UITabBar {
    weak var quickAccessView: UIView? // 使用weak避免循环引用
    
    override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard let quickAccessView = quickAccessView, !quickAccessView.isHidden else {
            return super.hitTest(point, with: event)
        }
        
        // 将TabBar坐标系的点转换为quickAccessView的坐标系
        let targetPoint = convert(point, to: quickAccessView)
        if quickAccessView.bounds.contains(targetPoint) {
            return quickAccessView.hitTest(targetPoint, with: event)
        }
        
        return super.hitTest(point, with: event)
    }
}

3. 修正TabBarController中的错误代码

移除viewDidAppear中错误的frame设置,并传递quickAccessView引用给自定义TabBar:

final class MainTabBarController: UITabBarController {
   private lazy var quickAccessView: QuickAccessView = .fromNib()
    var quickAccessSupportedTabBar: QuickAccessSupportedTabBar {
        guard let tabBar = self.tabBar as? QuickAccessSupportedTabBar else {
            fatalError("TabBar must be of type QuickAccessSupportedTabBar")
        }
        return tabBar
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tabBar.backgroundColor = .white
        setupUI() // 移到viewDidLoad中执行
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // 移除错误的frame设置代码
    }
}

extension MainTabBarController{
    private func setupUI(){
        setupQuickAcessView()
        addQuickAcessViewConstraints()
    }
}

// MARK: - Setting Up Quick Access view
extension MainTabBarController {
    private func setupQuickAcessView(){
        self.quickAccessSupportedTabBar.addSubview(quickAccessView)
        // 传递quickAccessView引用给自定义TabBar
        self.quickAccessSupportedTabBar.quickAccessView = quickAccessView
    }
    
    private func addQuickAcessViewConstraints(){
        quickAccessView.snp.makeConstraints { make in
            make.left.right.equalTo(self.quickAccessSupportedTabBar)
            make.height.equalTo(66)
            make.bottom.equalTo(self.quickAccessSupportedTabBar.snp.top)
        }
    }
}

4. 规范TabBar高度修改方式

避免直接修改tabBar.frame.size.height,可在自定义TabBar中重写intrinsicContentSize:

class QuickAccessSupportedTabBar: UITabBar {
    override var intrinsicContentSize: CGSize {
        return CGSize(width: super.intrinsicContentSize.width, height: 150) // 自定义高度
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:35:47