【问题标题】:Detecting a touch anywhere on the screen检测屏幕上任意位置的触摸
【发布时间】:2014-12-09 11:34:43
【问题描述】:

我想知道用户何时触摸了我的应用屏幕上的任何位置。

我已经研究过使用 -(UIResponder *)nextResponder 但不幸的是这不起作用,因为我还自动重新加载了一个表,所以当发生这种情况时会触发它。

我还尝试了一个手势识别器,代码如下。但这只会识别视图上的触摸。由于我有很多按钮,用户将使用它来操作应用程序。我想避免在屏幕上的每个按钮和段控件中添加手势识别器或代码

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOnView:)];
[self.mainView addGestureRecognizer:tap];

- (void)tapOnView:(UITapGestureRecognizer *)sender
{
    //do something
}

我也尝试过 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event ,但这与手势识别器有相同的问题。

我想知道是否有任何方法可以完成这项任务。我希望我能够从 nextResponder 中识别事件的类型,然后我可以检测它是否是按钮。

编辑:我正在处理这个问题的原因是我的应用程序需要保持活动状态并且无法锁定屏幕(所以我禁用了屏幕锁定)。为避免过度使用电量,我需要调暗屏幕,然后在触摸应用程序后将亮度恢复到原始水平。我需要这个功能只出现在我的 1 个视图控制器上。

【问题讨论】:

标签: ios objective-c cocoa-touch uigesturerecognizer uiresponder


【解决方案1】:

您可以将您的UITapGestureRecognizer 附加到您的[[UIApplication sharedApplication] keyWindow]

或者,您可以覆盖您的根 UIViewhitTest:

您是否希望完成某项特定任务?可能有比分配“任何地方”手势更好的方法。

编辑:使用hitTest:

@interface PassthroughView : UIView
@property (readonly) id target;
@property (readonly) SEL selector;
@end
@implementation PassthroughView
- (void)setTarget:(id)target selector:(SEL)selector {
  _target = target;
  _selector = selector;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
  [_target performSelector:_selector];
  return nil;
}
@end


@implementation YourUIViewController {
  PassthroughView *anytouchView;
}
- (void)viewDidLoad {
  // Add this at the end so it's above all other views.
  anytouchView = [[PassthroughView alloc] initWithFrame:self.view.bounds];
  [anytouchView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
  [anytouchView setTarget:self selector:@selector(undim)];
  [anytouchView setHidden:YES];
  [self.view addSubview:anytouchView];
}
- (void)undim {
  [anytouchView setHidden:YES];
}
- (void)dim {
  [anytouchView setHidden:NO];
}
@end

【讨论】:

  • 我在我的问题中添加了额外的细节
  • [[UIApplication sharedApplication] keyWindow] 不适用于按钮
  • 我已经更新了我的答案,向您展示如何使用hitTest: 来监听触摸事件,同时仍然让您的应用程序正常运行。
  • 谢谢,这可行,但需要研究另一个问题,因为它看起来可能更适合我的解决方案
  • 我认为这个解决方案可能只适用于“YourUIViewController”。如何在整个应用程序中捕获点击事件。我们不能一直在所有视图控制器中添加 PassthroughView。有什么解决办法吗?
【解决方案2】:

您的修改使您的问题更加清晰。

我这样做的原因是我的应用需要保持活跃 并且屏幕无法锁定(所以我禁用了屏幕锁定)。 为避免过度用电,我需要调暗屏幕,但随后 应用程序启动后将亮度恢复到原始水平 感动。

由于您正在控制屏幕亮度,您可以在调暗屏幕之前在您的根控制器顶部添加一个透明视图控制器,它只执行一项工作,使用 Tap 手势收听点击。在点击时,您可以关闭视图控制器并将亮度调整到以前的状态。

这样做您不必担心按钮被点击,因为它们将位于透明视图控制器下方。由于它是一个位于堆栈顶部的全新视图控制器,因此您也不必修改现有代码。

【讨论】:

  • 但这不意味着这个透明视图会阻止对按钮和其他功能的访问吗?
  • @Remixed123 它是顶部的新视图控制器,因此它可以接收屏幕上的所有触摸。
【解决方案3】:

好的,我之前也遇到过类似的问题。

我记得我将 UIWindow 子类化为全屏检测,并使其成为First responder

比我从子类覆盖要处理的触摸

您还可以使用代码识别被触摸的控件

#import <QuartzCore/QuartzCore.h>

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view setMultipleTouchEnabled:YES];
}

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

    // Enumerate over all the touches 
    [touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
        // Get a single touch and it's location
        UITouch *touch = obj;
        CGPoint touchPoint = [touch locationInView:self.view];
        ...
    }];
}

禁用屏幕锁定我使用了以下代码:

[[UIApplication sharedApplication] setIdleTimerDisabled:YES];

我使用以下功能调暗或增加屏幕亮度

[[UIScreen mainScreen] setBrightness:0.0f]; //and
[[UIScreen mainScreen] setBrightness:1.0f];

【讨论】:

  • -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 在按下按钮时不会被触发。我错过了什么吗?
  • 希望你不要忘记通过响应者链传递事件的概念。 [self.nextResponder touchesBegan:touches withEvent:event];
  • 另外,由于 [NSWindow makeFirstResponder:] 是一个窗口方法,只有在窗口中添加了相应的视图后才有意义。
  • 按下按钮永远不会进入 -(void)touchesBegan: 所以我没有机会通过响应者链传递事件。当我按下视图时它会进入。
  • 能否在子类 UIWindow 中添加日志 - (void)sendEvent:(UIEvent *)event { }。验证触摸事件的接收。
【解决方案4】:

正如 Ian MacDonald 所述,使用 hitTest:: 是检测应用范围内用户交互的绝佳解决方案,包括何时选择按钮、文本字段等。

我的解决方案是继承 UIWindow 并实现 hitTest 方法。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

   // do your stuff here

   // return nil if you want to prevent interaction with UI elements
   return [super hitTest:point withEvent:event];
}

【讨论】:

  • 由于查看“冒泡”触摸事件,这是我能找到的唯一可行的解​​决方案。谢谢!
  • 您能否提供更多关于如何使用 UIWindow 子类的详细信息 - 比如初始化、在当前窗口中显示等?
猜你喜欢
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多