只要用户正在进行交互,就会显示一个菜单

时间:2012-01-31 17:55:22

标签: ios user-interface uiview touch user-interaction

我一直在寻找一个解决方案,并且找不到一个幸运儿。如果之前有人问过,可能有人会指出它,或者帮助我一个想法。

我有UIViewController主持两个自定义视图。第一个自定义视图是全屏。第二个自定义视图实际上是一个从屏幕底部滑入视图的菜单,类似于带有自定义动画的工具栏,然后它应该滑出。

当前确认:菜单在延迟后(视图出现后)滑入视图,NSTimer开始计数。它会在视图中保留几秒钟,直到NSTimer触发另一个方法,然后该方法将菜单缩回。

一切正常。

我想要的是什么:如果用户开始与菜单交互,切换开关,滑块等,我希望菜单保留在视图中,延迟NSTimer的触发,直到用户完成交互。然后撤消菜单。

为了做到这一点,我在将菜单滑入视图的方法中使用了NSTimer,以便在X毫秒后触发另一个缩回菜单的方法。

在缩回菜单的方法中,我使计时器无效。

我覆盖了tocuhesBegan方法,看看交互区域是否属于菜单边界,如果是这样,NSTimer将被重置为另一个X毫秒。

问题:如果用户触摸菜单的背景,则可以,但如果用户与菜单中的开关,按钮和幻灯片进行互动,则menu.view不会注册触摸,这是有道理的,因为它们是前线并耗尽触摸事件,因此触摸事件不会传递到层次结构中。但另一方面,这是我的问题!!

我无法覆盖touchesBegan中每个元素中的每个menu.view方法。我怎样才能注册菜单区域内发生的那些触摸?

我尝试locationInView:nil在窗口内进行触摸,但是也没有注册与按钮和滑块等的交互。

感谢。

1 个答案:

答案 0 :(得分:1)

捕获视图层次结构中发生的所有触摸事件的一种解决方案是提供自定义UIWindow实现并覆盖sendEvent方法。所有事件均由UIApplication先收到,然后发送到UIWindow,然后再发送到包含触摸点的UIView。通过捕获UIWindow级别的事件,您可以确保可以拦截每个事件而无需覆盖每个控件。

创建一个自定义UIWindow类并实现sendEvent,如下所示:

- (void)sendEvent:(UIEvent *)event 
{
    // Notify app to reset menu timer
    // ...

    [super sendEvent:event];
}

使用自定义UIWindow而不是vanilla,取决于UI的实现方式。如果您使用的是Storyboard,那么您需要在您的app委托上实现window getter方法,如下所示:

- (UIWindow*)window
{
    if (!_window) {
        _window = [[CustomWindow alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
    }

    return _window;
}

否则,请在您的应用委托的application:didFinishLaunchingWithOptions:方法中创建自定义UIWindow的实例,而不是标准的实例。

您可以通过多种方式接收触摸事件通知。您可以使用NSNotificationCenter发送和订阅自定义通知,也可以在自定义UIWindow上实现委托属性,并将UIViewController设置为委托以接收触摸事件的通知。