添加UIHostingController为子控制器且设置isOpaque为false后无法点击下层按钮
问题原因
iOS的触摸事件传递逻辑与视图透明度无关:
isOpaque属性仅用于系统渲染性能优化,不会影响事件响应- 背景色设为
.clear仅代表视觉上透明,不会改变视图的触摸拦截行为
你当前将UIHostingController的view通过约束铺满了整个父视图,且UIHostingController的view默认开启isUserInteractionEnabled,所有触摸事件都会被这个上层视图拦截,不会向下传递到下层ViewController的按钮上。
解决方案
根据业务场景选择对应方案即可:
- 场景1:HostingController的视图无需响应任何触摸事件
直接关闭其视图的用户交互能力,事件会自动透传到下层:
// 在viewDidLoad中添加该行 ipView.view.isUserInteractionEnabled = false
也可以在SwiftUI层面直接设置:
let ipView = UIHostingController(rootView: InputView().allowsHitTesting(false))
- 场景2:HostingController的视图仅部分区域需要响应触摸
自定义透传视图类,重写命中测试逻辑,仅在点击位置落在需要响应的子元素上时才接收事件,其余情况透传:
class PassthroughView: UIView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let targetView = super.hitTest(point, with: event) return targetView == self ? nil : targetView } }
使用时将该自定义类作为UIHostingController的view的父容器,或者替换UIHostingController的根视图类即可。
- 场景3:HostingController的视图不需要铺满全屏
调整约束规则,仅为HostingController的view设置实际展示需要的尺寸约束,不要撑满整个父视图,未覆盖区域自然可以响应下层按钮的点击事件。
内容的提问来源于stack exchange,提问作者Chat Dp
相关产品推荐
相关产品推荐

