【问题标题】:Using UILongPressGestureRecognizer For Subviews of UIScrollview对 UIScrollview 的子视图使用 UILongPressGestureRecognizer
【发布时间】:2013-03-30 01:01:03
【问题描述】:

在过去的四个小时里,我尝试了许多 Stack Overlow 解决方案,但都没有解决我的问题。

来了,

  • 我有一个 UIScrollView
  • 在该 ScrollView 中有 一个自定义 UILabel 和 8 个自定义 UIImageViews
  • 我想检测长按
  • 类似这样的方法

    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressDidFire:)];
    longPress.minimumPressDuration = 0.5; [scroll addGestureRecognizer:longPress]; //scroll defined elsewhere

但是,如果我将滚动替换为滚动的任何子视图,则长按事件永远不会触发。

  1. 如何检测长按滚动视图的子视图?
  2. 这是一个相当混乱的 hack,但是,由于我可以检测到滚动视图的长按,有什么方法可以检测到 印刷机的位置,以便我可以看到哪个特定的子视图 被按下。

另外,(insert subview here).userInteractionEnabled = YES,我为滚动视图的所有子视图设置了这个属性,所以这应该不是问题。

我也尝试过使用 Stack Overflow 中其他地方建议的 touchesBegan 和 touchesEnded 方法。

此外,对于图像视图,我确实使用 for 循环为每个自定义图像视图设置了一个新的 UILongPressGestureRecognizer,因为我知道每个手势识别器 1 个视图规则。

来自第一次 iOS 开发者,

格雷厄姆

附:如果我能找到 1. 而不是凌乱的 2. 的解决方案,我真的更喜欢。


应要求提供更多代码:

在视图控制器的初始化中

 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressDidFire:)];
longPress.minimumPressDuration = 0.5;
[self.titleLabel addGestureRecognizer:longPress]; //titleLabel property initialized elsewhere
[mainView addSubview:self.titleLabel];

在“加载图像”方法中

for (NSData * dataImg in results) {
//Does some work turning data into an image, into an image view called img
        img.delegate = self;
        img.userInteractionEnabled = YES;
        UILongPressGestureRecognizer *aLongPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressDidFire:)];
        aLongPress.minimumPressDuration = 0.5;
        [img addGestureRecognizer:aLongPress];
        [imgContainer addSubview:img];
}

更多代码 + 注释

self.view (UIView)

->滚动(UIScrollView)

->->主视图(UIView)

->->->titleLabel(UILabel)

->->->imgContainer (UIView)

->->->->图像(UIImageViews)

[self.view addSubview:scroll];
[scroll addSubview:mainView];
[mainView addSubview:self.titleLabel];
[mainView addSubview:imgContainer];
[imgContainer addSubview:img]; //done 8x via for loop

感谢@RegularExpression 的回答,我现在知道 mainView 被按下了,但不是它的子视图,所以我需要找到一种方法来在它上面显示 mainView 的子视图。 :)

另一个更新,titleLabel 有效。 ImageViews 仍然不起作用。 :(

【问题讨论】:

  • 你如何将subViews 添加到UIScrollView
  • 正在加载代码,请稍等。谢谢您的帮助。 @老虎
  • 对不起,我之前误解了你,现在已经发布了我如何将视图添加到我的滚动视图@TheTiger

标签: iphone ios objective-c cocoa-touch uiscrollview


【解决方案1】:

代替

 [scroll addGestureRecognizer:longPress]; 

在子视图上添加手势,在你声明它们之后,在你将它们添加到滚动视图之前

 [subview addGestureRecognizer:longPress]; 

【讨论】:

  • ^忘记在上面标记你@mayuur
  • 好的,您能发布一下您是如何在滚动视图中添加视图的吗?
  • 对不起,我之前误解了你,现在已经发布了我如何将视图添加到我的滚动视图@mayuur
【解决方案2】:

由于您的 UIScrollView 是公共父级,这可能是您的手势识别器需要的位置。您可以通过查看操作中提供的点的位置来确定正在按下哪个子视图。因此,各个子视图不需要手势识别器。

所以,你会做这样的事情:

- (void)longPressDidFire:(UILongPressGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateEnded)
        CGPoint point = [sender locationInView:scroll];
        UIView *tappedView = [scroll hitTest:point withEvent:nil];

那么,你有被长按的视图。

其他可能导致动作不触发的事情是委托问题,或者滚动被拦截触摸的另一个视图包含。

HTH

【讨论】:

  • 这看起来很有趣,@RegularExpression,我去看看
  • 但是如何找到具体的 UIView,它给出的只是内存分配,因为有 8 个自定义 UIImageView,我不知道这是否可行。
  • 谢谢,这帮助我弄清楚主视图被点击了,而不是主视图的子视图。这很有帮助!
  • 查看我上面的回答,如果你喜欢,请点赞。 :) @RegularExpression
【解决方案3】:

您的代码似乎很好,我认为它应该可以工作。我使用了下面的代码,它对我来说工作正常。

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
longPress.delegate = (id)self;
longPress.minimumPressDuration=0.05;
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:longPress];

及其方法,

- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)sender {
   NSLog(@"detected");

if (sender.state == UIGestureRecognizerStateEnded){
     UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Alert" message:@"YES"    delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
     [alert show];
   } 
}

正如你所说,我在这里将 imageView 作为滚动视图的子视图

【讨论】:

  • 谢谢,我在上面发布了我的代码,除了 (id)self 之外,它与你的非常相似。但不幸的是,它不起作用。 @murali
  • 对不起,我之前误解了你,现在已经发布了我如何将视图添加到我的滚动视图@murali
  • Scrollview 在 xib 中或以编程方式添加? @GangstaGraham
【解决方案4】:

哇哦,它有效!

问题是:

imgContainer 是一个 带有空框架的 UIView,其中有几个 UIImageViews 作为子视图

我的印象是,当我向 imgContainer 添加子视图时,imgContainer 会展开。

不是真的

我必须将 imgContainer 的框架设置为与滚动视图相同的内容框架,然后一切正常。

我希望这个答案可以帮助像我这样的任何其他未来的 iOS 初学者。

【讨论】:

  • 有点像你一个人玩:/首先我们没有你的代码,我们只是回答了你的问题。现在看看你的问题,任何人都可以像你在这里给出的那样给出答案吗?我认为 NO 因为你知道你写了什么....任何方式快乐编码。
  • 我不是故意的。你们所有人都做得很好,用给你们的东西(尽管你们基本上和我有相同的代码)。尽管如此,我觉得有必要给出最终的、真实的答案,以防将来有人遇到这个问题。 @老虎
【解决方案5】:

我知道这有点晚了,并且已经选择了答案,但如果你有 iOS7,如果其他人想要一个很好的简单解决方案。

UILongPressGestureRecognizer 的委托中实现 gestureRecognizer:shouldRequireFailureOfGestureRecognizer:otherGestureRecognizer 选择器

检查otherGestureRecognizer是否是UIPanGestureRecognizer并返回YES,否则返回NO

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        return YES;
    }

    return NO;
}

滚动视图实际上会生成一个 UIScrollViewPanGestureRecognizer,它是私有 API 的一部分,但它是 UIPanGestureRecognizer 的子类,因此上述工作正常。

要支持 iOS6 或更低版本,您需要遍历 UIScrollView 的手势识别器,检测哪个是 UIPanGestureRecognizer 并在您的设备上执行 requireGestureRecognizerToFail 选择器UILongPressGestureRecogizer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多