自定义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
相关产品推荐
相关产品推荐

