如何禁用Vertical StackView内彩色视图点击并阻止触摸事件透传
嘿,这个问题我太熟了!iOS的触摸事件传递规则有时候确实会让人懵——你关闭子视图的「User Interaction Enabled」没用,是因为这个属性关闭后,系统会直接把触摸事件透传给父视图,所以父视图的tap手势还是会被触发。下面给你两个靠谱的解决方案:
方案一:让子视图主动拦截并消费触摸事件
这个思路是让子视图自己接住触摸事件,不往上传递。步骤如下:
- 先把三个彩色子视图的User Interaction Enabled重新打开(之前关闭反而会让事件透传,现在要打开)
- 二选一实现事件拦截:
- 方法A:重写子视图的触摸方法
给你的彩色视图自定义一个子类,重写touchesBegan方法,什么都不做就行:
之后把Purple、Green、Orange视图的类改成这个自定义子类,点击它们时事件就会被拦截,父视图的手势不会触发。class ColorBlockView: UIView { override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { // 空实现,直接消费触摸事件,不向父视图传递 } } - 方法B:给子视图添加空的tap手势
不需要自定义子类,直接给每个彩色视图加一个没有action的tap手势:
这样触摸子视图时,这个空手势会优先拦截事件,父视图的手势就不会收到触发信号了。// 给紫色视图加空手势 let purpleTap = UITapGestureRecognizer() purpleView.addGestureRecognizer(purpleTap) // 绿色、橙色视图同理 let greenTap = UITapGestureRecognizer() greenView.addGestureRecognizer(greenTap) let orangeTap = UITapGestureRecognizer() orangeView.addGestureRecognizer(orangeTap)
- 方法A:重写子视图的触摸方法
方案二:在父视图手势代理里过滤触摸点
如果你不想改动子视图的代码,就在父视图这边做判断,让手势只在点击父视图空白区域时触发:
- 让父视图遵循
UIGestureRecognizerDelegate协议 - 给父视图的tap手势设置
delegate = self - 实现代理方法,判断触摸点是否在子视图范围内:
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { guard let tapGesture = gestureRecognizer as? UITapGestureRecognizer else { return true } // 获取触摸点在父视图坐标系下的位置 let touchLocation = tapGesture.location(in: self) // 检查触摸点是否落在三个彩色子视图里 let isTouchOnColorView = purpleView.frame.contains(touchLocation) || greenView.frame.contains(touchLocation) || orangeView.frame.contains(touchLocation) // 如果是点击子视图,就返回false,阻止手势触发;否则返回true return !isTouchOnColorView }
两种方法都能完美解决你的问题,选哪种看你的代码结构和需求就行~
内容的提问来源于stack exchange,提问作者Bilbo Baggins
相关产品推荐
相关产品推荐

