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

自定义UINavigationBar高度后交互区域异常问题求助

嘿,这个问题我太熟了!你遇到的核心问题是UINavigationBar默认的点击检测范围还是它原来的默认高度,你扩展出来的那部分区域不在它的hitTest检测范围内,所以你加的按钮自然点不动。下面给你一套完整的解决办法,直接就能用:

解决步骤与优化代码

1. 重写hitTest方法,扩大点击检测范围

我们需要重写导航栏的hitTest(_:with:)方法,让它把自定义高度的整个区域都纳入点击检测,同时还要遍历子视图,确保你添加的按钮能被正确识别点击事件。

2. 在layoutSubviews中正确布局所有元素

不仅要调整导航栏本身的frame,还要确保内部的背景、内容视图,以及你自己添加的按钮都布局在扩展后的区域内。

完整代码示例

@IBDesignable class CustomNavigationBar: UINavigationBar {
    @IBInspectable var customHeight: CGFloat = 88
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // 调整导航栏自身的frame到自定义高度
        frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: customHeight)
        
        // 调整导航栏内部系统子视图的布局(适配扩展高度)
        for subview in subviews {
            let className = NSStringFromClass(subview.classForCoder)
            // 调整背景视图的高度
            if className.contains("BarBackground") {
                subview.frame = CGRect(x: 0, y: 0, width: frame.width, height: customHeight)
            }
            // 调整内容容器的位置(避开状态栏)
            else if className.contains("ContentViews") {
                let statusBarHeight = UIApplication.shared.statusBarFrame.height
                subview.frame = CGRect(
                    x: subview.frame.origin.x,
                    y: statusBarHeight,
                    width: subview.frame.width,
                    height: customHeight - statusBarHeight
                )
            }
        }
        
        // 示例:添加一个位于扩展区域的自定义按钮
        let customButton = UIButton(type: .system)
        customButton.setTitle("扩展按钮", for: .normal)
        // 把按钮放在导航栏底部区域(扩展出来的部分)
        customButton.frame = CGRect(x: frame.width - 80, y: customHeight - 40, width: 70, height: 30)
        customButton.addTarget(self, action: #selector(customButtonTapped), for: .touchUpInside)
        
        // 避免重复添加按钮
        if !subviews.contains(customButton) {
            addSubview(customButton)
        }
    }
    
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        // 先判断点击点是否在自定义导航栏的范围内
        if point(inside: point, with: event) {
            // 倒序遍历子视图,优先检测上层视图的点击
            for subview in subviews.reversed() {
                let convertedPoint = subview.convert(point, from: self)
                if let hitView = subview.hitTest(convertedPoint, with: event) {
                    return hitView
                }
            }
            return self
        }
        return super.hitTest(point, with: event)
    }
    
    @objc private func customButtonTapped() {
        print("扩展区域的按钮被成功点击啦!")
    }
}

额外注意事项

  • 如果你用AutoLayout来布局自定义按钮,记得在layoutSubviews里更新约束,确保按钮的位置落在扩展后的导航栏区域内。
  • 如果是通过导航控制器使用这个自定义导航栏,初始化时要指定自定义类:
let navController = UINavigationController(navigationBarClass: CustomNavigationBar.self, toolbarClass: nil)
navController.viewControllers = [YourRootViewController()]

内容的提问来源于stack exchange,提问作者Mr.P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:20:25