iPhone 中的同级子视图不接收触摸

发布于 2024-12-21 17:38:19 字数 1709 浏览 2 评论 0原文

我有一个视图(parent),它有两个子视图,一个在顶部(topChild),另一个在另一个(bottomChild)上。

如果我点击屏幕,则只有 topChildparent 接收触摸事件。

我应该更改什么才能将触摸事件传播到 bottomChild

代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    MYView* parent = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    parent.tag = 3;
    parent.backgroundColor = [UIColor redColor];

    MYView* bottomChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 90, 90)];
    bottomChild.tag = 2;
    bottomChild.backgroundColor = [UIColor blueColor];
    [parent addSubview:bottomChild];

    MYView* topChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];
    topChild.tag = 1;
    topChild.backgroundColor = [UIColor greenColor];
    [parent addSubview:topChild];
    [self.view addSubview:parent];
}

其中MYViewUIView的子类,仅记录touchesBegan

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"%d", self.tag);
    [super touchesBegan:touches withEvent:event];
}

结果:

在此处输入图像描述

触摸绿色区域会产生以下日志:

TouchTest[25062:f803] 1
TouchTest[25062:f803] 3

我的第一个想法是使 parent 将所有 touchesSomething 调用传播到其子级,但(A)我怀疑可能有一个更简单的解决方案,(B)我不知道哪个孩子将事件发送给父母,并且发送touchesSomething 向同一个视图发送两次消息可能会导致恶作剧。

提出问题后,我发现这个 post 建议覆盖 hitTest< /code> 更改接收触摸的视图。我将尝试这种方法并更新问题(如果有效)。

I have a view (parent) with two subviews, one on top (topChild) of the other (bottomChild).

If I tap on the screen only topChild and parent receive the touch event.

What should I change to propagate the touch event to bottomChild as well?

The code:

- (void)viewDidLoad
{
    [super viewDidLoad];
    MYView* parent = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    parent.tag = 3;
    parent.backgroundColor = [UIColor redColor];

    MYView* bottomChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 90, 90)];
    bottomChild.tag = 2;
    bottomChild.backgroundColor = [UIColor blueColor];
    [parent addSubview:bottomChild];

    MYView* topChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];
    topChild.tag = 1;
    topChild.backgroundColor = [UIColor greenColor];
    [parent addSubview:topChild];
    [self.view addSubview:parent];
}

Where MYView is a subclass of UIView that only logs touchesBegan.

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"%d", self.tag);
    [super touchesBegan:touches withEvent:event];
}

The result:

enter image description here

Touching the green area produces the following log:

TouchTest[25062:f803] 1
TouchTest[25062:f803] 3

My first idea was to make parent propagate all the touchesSomething calls to its children but (A) I suspect there might be an easier solution and (B) I don't know which child sent the event to parent, and sending touchesSomething messages twice to the same view might cause shenanigans.

After asking the question I've found this post that suggests to override hitTest to change the view that receives the touches. I will try this approach and update the question if it works.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

带上头具痛哭 2024-12-28 17:38:19

这是一个有趣的问题,最好通过重新思考事物的结构方式来解决。但要使其按照您建议的方式工作,您需要捕获当前顶视图中的触摸事件,将其传递给父视图,然后将其向下传播到父视图的所有子视图。要实现此功能,您需要 touchesBegan:(或用于拦截触摸的任何其他方法)在所有视图中不执行任何操作,仅在父视图调用的方法中执行操作。

这实际上是另一种说法,不处理视图中的触摸,捕获它们但通知父视图视图,然后根据需要调用子视图方法以产生您想要的效果。

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    // Do nothing, parent view calls my parentNotifiedTouchesBegan method
    [self.superview touchesBegan:touches withEvent:event];
}

- (void) parentNotifiedTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    // Act on the touch here just as my sibling views are doing
}

请注意,我在该代码中将 super 更改为 self.superview。您可能也可能不想调用 super 的方法,具体取决于您正在做什么,以及调用的位置可能位于 parentNotifiedTouchesBegan 中。

当然,您可以知道哪个子视图发送了事件,只需使用自定义方法通知超级视图,而不是调用其 touchesBegan: 。使用 self 参数。

It's an interesting problem you have that is probably something best addressed through a rethink of the way you have things structured. But to make it work the way you suggest you need to catch the touch event in the current top view, pass it to the parent and then propagate it down through all subviews of the parent view. To make this work you would need the touchesBegan: (or whatever other method you use to intercept the touch) to do nothing in all the views, doing the action only in the method called by the parent view.

Which is really another way of saying don't handle touches in the views, catch them but notify the parent view view and then call subview methods as required to cause the effect you want.

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    // Do nothing, parent view calls my parentNotifiedTouchesBegan method
    [self.superview touchesBegan:touches withEvent:event];
}

- (void) parentNotifiedTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    // Act on the touch here just as my sibling views are doing
}

Note I changed super to self.superview in that code. You may or may not also want to call super's method depending on what you are doing, and the place to call that may be in parentNotifiedTouchesBegan.

You can know which subView sent the event of course, just use a custom method to notify the superview instead of calling its touchesBegan:. Use a self argument.

贱人配狗天长地久 2024-12-28 17:38:19

如果您不需要触摸孩子,请设置

bottomChild.userInteractionEnabled = NO;
topChild.userInteractionEnabled = NO;

If you don't need the touches on the children then set

bottomChild.userInteractionEnabled = NO;
topChild.userInteractionEnabled = NO;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文