【问题标题】:How to "transfer" first responder from one UIView to another?如何将第一响应者从一个 UIView“转移”到另一个?
【发布时间】:2010-11-27 23:15:01
【问题描述】:

我有一个 UIView 子类(CustomView 用于此问题),它自己处理所有 touches 事件(开始、移动、结束、取消)。我还有一个 UIButton,它是 CustomView 的兄弟,与它重叠。

例如,我的视图层次结构如下所示:

  • UIView(控制器的视图)
    • 带框架的CustomView (0, 0, 300, 300)
    • 带框架的 UIButton (0, 0, 100, 50)

我希望 CustomView 在用户拖出 UIButton 后捕获触摸事件。通过调试日志,似乎UIControlEventTouchDragExit 事件是要拦截的事件(尽管直到触摸距离按钮大约 100 像素时它才会触发,但这对于这个问题并不重要)。

理想情况下,当拖动退出事件被触发时,按钮将停止接收触摸移动事件,CustomView 将收到一个touchesBegan 事件(即使我需要以某种方式自己伪造一个),以及所有未来的触摸事件(@ 987654327@ 等)将被发送到 CustomView。

我尝试了以下方法,但没有任何效果:

-(void)btnTouchDragExit:(id)sender
{
    UIButton * btn = sender;
    [btn resignFirstResponder];
    [customView becomeFirstResponder];
}

我认为底层 UITouch 对象(在触摸事件中是一致的)没有被重新定位为指向 CustomView。怎样才能达到想要的效果?

【问题讨论】:

    标签: iphone uiview uibutton uitouch first-responder


    【解决方案1】:

    只需使用 hitTest:withEvent: 来确定哪个视图“应该”接收事件,然后将事件转发到适当的视图。在事件转到按钮之前,您可能需要做一些跳舞来拦截事件,但这就是 hitTest:withEvent: 的用途。

    【讨论】:

    • 通过子类化 UIButton 并覆盖 touchesMoved,我已经能够做到这一点(遍历调用 hitTest 的超级视图树,直到找到其中有接触点的树)。但是,我必须手动将触摸事件转发(从那时起)到该视图。没有系统调用以便 Cocoa/UIWindow/UIApplication 将触摸发送到该新视图吗?在 Win32 中,它是 ReleaseCapture/SetCapture(newWnd)..
    • 在父视图上调用 hitTest:withEvent:,它会告诉你哪个子视图将是事件的第一响应者。一旦你弄清楚了,只需致电touches(Began|Moved|Ended):withEvent:
    • 这行得通,但这是我试图避免的,即因为这需要子类化,并且这样做我只能在自定义按钮(而不是圆角矩形或任何其他按钮)上具有这种行为。我还看到将触摸事件转发到 UIScrollViews 和 UIWebViews 之类的东西时会发生奇怪的事情,因此它可能不是一个完全通用的解决方案。我会暂时搁置这个问题,看看是否还有其他建议。
    【解决方案2】:

    您必须覆盖 canBecomeFirstResponder 才能返回 YES,否则 becomeFirstResponder 什么也不做。这已经在UIControls 上完成,但不是在UIViews 上

    【讨论】:

    • 将它添加到我的 UIView 子类没有帮助。仍然需要继承 UIButton 并强制重定向触摸事件。从概念的角度来看,似乎为了让它工作,我无论如何都不会调用[customView becomeFirstResponder],但应该调用类似[UIApplication assignFirstResponder:customView] 或其他一些静态/全局函数。
    猜你喜欢
    • 2014-07-05
    • 1970-01-01
    • 2015-12-27
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多