【问题标题】:iOS: Transfer ownership of UIView while touches happening?iOS:在发生触摸时转移 UIView 的所有权?
【发布时间】:2012-04-05 15:12:01
【问题描述】:

收到touchesBegan的那一刻,我想removeFromSuperview被触摸的视图和addSuperview到一个新的父视图,然后继续接收触摸。但是我发现有时这不起作用。具体来说,touchesMovedtouchesEnded 永远不会被调用。

是否有使这项工作正常工作的技巧?这是为了实现拖放行为,其中视图最初位于滚动视图内。

谢谢。

【问题讨论】:

    标签: ios uiview uiscrollview touchesbegan touchesmoved


    【解决方案1】:

    代替:

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

    仅供参考:

    [newParentView addSubview:transferView];
    

    documentation 声明:“视图只能有一个超级视图。如果视图已经有一个超级视图并且该视图不是接收者,则此方法会在将接收者设为新的超级视图之前删除之前的超级视图。”

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

    【讨论】:

    • 这应该是公认的答案,因为没有必要在超级视图中管理拖动以实现 OP 的目标。只需删除 removeFromSuperView 即可。谢谢walapu
    • 很好的答案,这很有帮助!
    【解决方案2】:

    您需要在超级视图中处理您的触摸,而不是在您想要切换的视图中。这将允许您在不丢失触摸事件的情况下切换视图。但是,当您这样做时,您必须测试自己是否在要切换的特定子视图中发生触摸。这可以通过多种方式完成,但这里有一些方法可以帮助您入门:

    将 Rects/Point 转换为另一个视图:

    [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 addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewPanned:)]];
    

    现在 self(将是管理其子视图的超级视图)将响应平移动作。

    【讨论】:

    • 不知道为什么会这样。可以发代码吗?顺便说一句,是什么阻止您使用 UIGestureRecognizer?在我考虑过使用 Touches 的几乎所有情况下,我发现现有的 UIGestureRecognizer 或子类化 UIGestureRecognizer 效果更好(而且我可以重用它)。
    • 如果你使用的是 UIPanGestureRecognizer,touchesBegan 不应该出现在你的代码中。您应该像这样设置一些目标方法:- (void) viewPanned:(UIPanGestureRecognizer)pan。当你初始化识别器时,你设置它的目标:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewPanned:)]。该方法将被重复调用,您可以检查状态并执行适当的操作:If (pan.state == UIGestureRecognizerStateBegan){ .......}If (pan.state == UIGestureRecognizerStateChanged{ ..... } 等...
    • 我扩大了答案以反映这一点。
    • 我注意到您正在删除视图并创建另一个视图以添加到目标。我肯定会发现,当我从超级视图中删除原件时,它会停止接收触摸,即使我之后立即将其重新添加到另一个视图。
    猜你喜欢
    • 1970-01-01
    • 2011-04-19
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    相关资源
    最近更新 更多