userInteractionEnabled = YES时如何将触摸事件传递给superview?
Posted
技术标签:
【中文标题】userInteractionEnabled = YES时如何将触摸事件传递给superview?【英文标题】:How to pass the touch event to superview when userInteractionEnabled = YES? 【发布时间】:2014-05-06 14:23:54 【问题描述】:我有以下设置。
+- XXXCustomControl : UIControl -------+
| A |
| +- ContentView -------------------+|
| | ||
| | B ||
| | ||
| +---------------------------------+|
+--------------------------------------+
作为 UIControl 子类的 XXXCustomControl。它包含一个名为 contentView 的 UIView 类型的子视图,其大小小于控件的区域。
那个视图有.userInteractionEnabled = YES
;
我需要将该属性设置为 YES,因为水平滚动视图偶尔会放在其中,并且它们需要是可滚动的。如果超级视图(在我们的例子中,内容视图不允许用户交互,这会被子视图继承。)
但与此同时,这个XXXCustomControl
需要在其内容视图中不包含滚动视图时(不仅在区域 A 中,而且在区域 B 中)是可点击的。
所以我在这里有“利益冲突”,因为我要么
1)将内容视图设置为userInteractionEnabled = NO
,然后我可以在A和B的内容视图区域中点击空控件,但是我将放置在那里的滚动视图将无法滚动。..
2)将内容视图设置为userInteractionEnabled = YES
,但是如果控件为空,我只能点击区域A来触发触摸事件。
我想出的一个想法是,我将属性默认设置为 NO,当我填充 contentView 时,我将其设置为 yes。当我清除 contentView 时,我将属性设置回 no。 基本上我希望它一直设置为yes,当它为空时,强制contentView将touchUpInside事件传递给它的superview。
这可能吗?
【问题讨论】:
如果你只关心点击,为什么不向子视图添加一个手势识别器,它的动作与父视图中的手势识别器相同?这似乎是最简单的实现。 你为什么不给答案?迈克尔为我工作...... 迟到总比不到好... 我认为这不是利益冲突的定义,也许是利益冲突? :) 【参考方案1】:您可以尝试在内部视图中覆盖pointInside:withEvent:
方法。当您想将触摸转发到超级视图时,这将允许您返回 NO:
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
if( /* You have content, and you want to receive touches */)
return YES;
else
return NO;
【讨论】:
这也适用于包含在容器视图中的视图 - 允许某些控件存在于容器(超级)视图中。只需通过子视图帧进行交互 - 如果没有命中则返回 NO【参考方案2】:您可以子类化您的子视图,并实现
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
if (!touchedContent)
[[self nextResponder] touchesBegan:touches withEvent:event];
else
[super touchesBegan:touches withEvent:event];
【讨论】:
【参考方案3】:您可以使用另一个 UIView 来“隐藏”子视图。 *详细信息:这个 UIView 是子视图的兄弟。它与您的子视图具有相同的大小和位置,背景颜色为透明色。 *说明:新的 UIView 将进行触摸,并自动将其传递给父视图。 这种方式不需要子类化您的子视图 - 这是一个故事板解决方案。请试试这个。玩得开心!
【讨论】:
【参考方案4】:在超级视图中使用它,无需更改子视图代码(因为子视图可能从其他框架或 pod 引入):
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
UIView *view = [super hitTest:point withEvent:event];
if ([view isDescendantOfView:self])
NSLog(@"touched inside");
return view;
【讨论】:
【参考方案5】:- 斯威夫特
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool
if <#condition#> return true
else return false
【讨论】:
【参考方案6】:如果您想从超级视图(在您的情况下为 XXXCustomControl)而不是内部视图(在您的情况下为 ContentView)处理事件,您可以在您的超级视图中编写以下 swift 代码:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
guard let view = super.hitTest(point, with: event) else return nil
if view.isDescendant(of: self)
// your custom logic
return view
【讨论】:
以上是关于userInteractionEnabled = YES时如何将触摸事件传递给superview?的主要内容,如果未能解决你的问题,请参考以下文章
在 overlaySKScene 上设置 userInteractionEnabled=true/false 无效
userInteractionEnabled = YES时如何将触摸事件传递给superview?
iOS bug 日志-userInteractionEnabled
斯威夫特:userInteractionEnabled 用于纺车概念中的子视图
尽管 userInteractionEnabled = true,但 UIView 中的 UIButton 没有响应触摸事件