iOS:在触摸事件发生时转移UIView的所有权?

7
当我接收到 touchesBegan 时,我想将被触摸的视图removeFromSuperview并添加到一个新的父视图中,然后继续接收触摸。但是,我发现有时它不起作用。具体来说,touchesMovedtouchesEnded 没有被调用。
是否有技巧可以正确地实现此功能?这是为了实现拖放行为,其中视图最初位于滚动视图中。
谢谢。
2个回答

7

改为:

[transferView removeFromSuperView];
[newParentView addSubview:transferView];

仅使用:

[newParentView addSubview:transferView];

文档中指出:“视图只能有一个父视图。如果视图已经有一个父视图,而且不是接收者,则此方法在将其设置为新的父视图之前会删除先前的父视图。”

因此,不需要使用removeFromSuperView,因为它由addSubview处理。我注意到,removeFromSuperView会结束任何当前的触摸事件,而不调用touchesEnded。如果只使用addSubview,则不会中断触摸。


1
这应该是被接受的答案,因为不需要在父视图中管理拖动以实现OP的目标。只需删除removeFromSuperView即可。谢谢walapu - walkingbrad
非常好的答案,这很有帮助! - Max

0
你需要在父视图中处理触摸事件,而不是在要切换的视图中处理。这样可以在切换视图时保留触摸事件。但是,在这种情况下,你需要自己测试触摸是否发生在要切换的特定子视图中。有很多方法可以实现这一点,以下是一些方法供你参考:

将矩形/点转换为另一个视图:

[view convertRect:rect toView:subview];
[view convertPoint:point toView:subview];

以下是一些测试点是否位于视图中的方法:

[subView hitTest:point withEvent:nil];
CGRectContainsPoint(subview.frame, point); //No point conversion needed
[subView pointInside:point withEvent:nil];

一般来说,最好使用UIGestureRecognizers。例如,如果您正在使用UIPanGestureRecognizer,则应创建一个手势识别器可以调用的方法,在该方法中执行您的工作。例如:
- (void) viewPanned:(UIPanGestureRecognizer *)pan{
    if (pan.state == UIGestureRecognizerStateBegan){
        CGRect rect = subView.frame;
        newView = [[UIView alloc] initWithFrame:rect];
        [subView removeFromSuperview];
        [self addSubview:newView];
    } else if (pan.state == UIGestureRecognizerStateChanged){
        CGPoint point = [pan locationInView:self];
        newView.center = point;
    } else {
        //Do cleanup or final view placement
    }
}

然后您初始化识别器,将其分配给目标(通常为self),并添加它:

[self addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewPanned:)]];

现在自身(即管理其子视图的父视图)将响应平移手势。


不确定为什么会这样。你能发一下代码吗?顺便问一下,有什么阻止你使用UIGestureRecognizer吗?在我考虑使用Touches的几乎每种情况下,我都发现使用现有的UIGestureRecognizer或子类化UIGestureRecognizer更好(而且我可以重用它)。 - Aaron Hayman
如果你正在使用库存的UIPanGestureRecognizer,你的代码中不应该有touchesBegan。你应该设置一些目标方法,像这样:- (void)viewPanned:(UIPanGestureRecognizer)pan。当你初始化识别器时,你设置它的目标:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewPanned:)]。那个方法会被反复调用,你可以检查状态并执行适当的操作:if (pan.state == UIGestureRecognizerStateBegan){ .......}或者if (pan.state == UIGestureRecognizerStateChanged{ ..... }等等... - Aaron Hayman
我扩展了我的答案以反映这一点。 - Aaron Hayman
我注意到你正在移除视图并创建另一个视图添加到目标上。我发现当我从父视图中移除原始视图时,即使我立即将其重新添加到另一个视图中,它也不再接收触摸事件。 - user945620

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接