userInteractionEnabled = YES时如何将触摸事件传递给superview?

时间:2014-05-06 14:23:55

标签: ios objective-c cocoa-touch

我有以下设置。

+- XXXCustomControl : UIControl -------+
| A                                    |
|   +- ContentView -------------------+|
|   |                                 ||
|   |  B                              ||
|   |                                 ||
|   +---------------------------------+|
+--------------------------------------+ 

XXXCustomControl是UIControl的子类。它包含一个名为contentView的UIView类型的子视图,其大小小于Control的区域。 该视图具有.userInteractionEnabled = YES;

我需要将该属性设置为YES,因为水平滚动视图会偶尔放入其中,并且它们需要可滚动。如果超级视图(在我们的案例中,内容视图不允许用户交互,则会继承子视图。) 但同时这个XXXCustomControl在其内容视图中不包含滚动视图时不仅需要在区域A中而且在区域B中都可以进行tappable。

所以我在这里有“利益冲突”,因为我要么

1)将内容视图设置为userInteractionEnabled = NO,然后我可以在A和B的内容视图区域中点击空控件,但是我将放在那里的滚动视图将无法滚动..

2)将内容视图设置为userInteractionEnabled = YES但是,如果Control为空,我只能点击区域A来触发触摸事件。

我提出的一个想法是我默认将属性设置为NO,当我填充contentView时,我将其设置为yes。当我清除contentView时,我将属性设置为no。 基本上我希望它一直设置为yes,当它为空时,强制contentView将touchUpInside事件传递给它的superview。

这可能吗?

6 个答案:

答案 0 :(得分:15)

您可以尝试在内部视图中覆盖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;
    }
}

答案 1 :(得分:4)

您可以子类化子视图,并实现

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!touchedContent) {
        [[self nextResponder] touchesBegan:touches withEvent:event];
    } else {
        [super touchesBegan:touches withEvent:event];
    }
}

答案 2 :(得分:1)

您可以使用另一个UIView来“隐藏”子视图。

*详情:这个UIView是子视图的兄弟姐妹。它具有与子视图相同的大小和位置,背景颜色为浅色。

*解释:新的UIView将触摸,并自动将其传递给superview。

这种方式不需要子类化您的子视图 - 这是一个故事板解决方案。
请尝试这个。玩得开心!

答案 3 :(得分:0)

在超级视图中使用此功能,而不更改子视图代码(因为子视图可​​能是从其他框架或窗格引入的):

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *view = [super hitTest:point withEvent:event];
    if ([view isDescendantOfView:self])
    {
        NSLog(@"touched inside");
    }
    return view;
}

答案 4 :(得分:0)

-斯威夫特

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    if <#condition#> { return true }
    else { return false }
}

答案 5 :(得分:0)

如果要从Superview(在您的情况下为XXXCustomControl)而不是内部视图(在您的情况下为ContentView)处理事件,则可以在Superview中编写以下快速代码:

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
}