简体   繁体   English

使用UILongPressGestureRecognizer查看UIScrollview的子视图

[英]Using UILongPressGestureRecognizer For Subviews of UIScrollview

For the past four hours, I have tried many Stack Overlow solutions but none have helped solve my problem. 在过去的四个小时里,我尝试了很多Stack Overlow解决方案,但没有一个能帮我解决问题。

Here it is, 这里是,

  • I have a UIScrollView 我有一个UIScrollView
  • Within that ScrollView there is one custom UILabel and 8 custom UIImageViews 在该ScrollView中,有一个自定义UILabel和8个自定义UIImageViews
  • I want to detect a long press 我想检测一下长按
  • Something like this works 像这样的东西有效

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

However, if I replace the scroll with any subviews of scroll, the long press event never fires. 但是,如果我将滚动替换为滚动的任何子视图,则长按事件永远不会触发。

  1. How do I detect a long press of a subview of a scroll view? 如何检测长按滚动视图的子视图?
  2. This is quite a messy hack, however, since I can detect long presses of a scroll view, is there any way where I can detect the position of the press so that I can see which specific subview is being pressed. 然而,这是一个非常混乱的黑客,因为我可以检测到滚动视图的长按,有什么方法可以检测印刷机的位置,以便我可以看到正在按下哪个特定的子视图。

Also, (insert subview here).userInteractionEnabled = YES , I set this property for all my subviews of the scroll view, so this should not be a problem. 另外, (insert subview here).userInteractionEnabled = YES ,我为滚动视图的所有子视图设置了此属性,因此这应该不是问题。

I have also tried using touchesBegan and touchesEnded method as suggested elsewhere in Stack Overflow. 我也尝试过使用touchesBegan和touchesEnded方法,如Stack Overflow中其他地方所建议的那样。

Also, for the image views, I do set a new UILongPressGestureRecognizer for every custom image view, using a for loop, as I am aware of the 1 view per gesture recognizer rule. 此外,对于图像视图,我使用for循环为每个自定义图像视图设置新的UILongPressGestureRecognizer,因为我知道每个手势识别器规则的1个视图

From A First Time iOS Developer, 来自第一次iOS开发者,

Graham 格雷厄姆

PS I'd really prefer if I could find a solution for 1. rather than the messy 2. PS我真的更喜欢我能找到1的解决方案,而不是凌乱的2。


More Code As Requested: 更多代码要求:

In the Init of the view Controller 在Init视图控制器中

 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];

In a "load images" method 在“加载图像”方法中

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];
}

Even More Code + Notes 更多代码+笔记

self.view (UIView) self.view(UIView)

->scroll (UIScrollView) - >滚动(UIScrollView)

->->mainView (UIView) - > - > mainView(UIView)

->->->titleLabel (UILabel) - > - > - > titleLabel(UILabel)

->->->imgContainer (UIView) - > - > - > imgContainer(UIView)

->->->->images (UIImageViews) - > - > - > - > images(UIImageViews)

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

Thanks to @RegularExpression's answer, I now am aware that the mainView is getting pressed, but not its subviews, so I need to find a way to display the mainView's subviews above it. 感谢@ RegularExpression的回答,我现在知道mainView正在被按下,但不是它的子视图,所以我需要找到一种方法来显示它上面的mainView的子视图。 :) :)

Another update, titleLabel works. 另一个更新,titleLabel工作。 ImageViews still don't work though. ImageViews仍然无法正常工作。 :( :(

I know this is a bit late and an answer has been chosen, but in case someone else wants a nice simple solution if you've got iOS7. 我知道这有点晚了,已经选择了一个答案,但是如果你有iOS7,别人想要一个很好的简单解决方案。

Inside your delegate of the UILongPressGestureRecognizer implement the gestureRecognizer:shouldRequireFailureOfGestureRecognizer:otherGestureRecognizer selector 在你的UILongPressGestureRecognizer委托中,实现gestureRecognizer:shouldRequireFailureOfGestureRecognizer:otherGestureRecognizer选择器

Check if otherGestureRecognizer is a UIPanGestureRecognizer and return YES, otherwise return NO 检查otherGestureRecognizer是否为UIPanGestureRecognizer并返回YES,否则返回NO

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

    return NO;
}

The scroll view will actually produce a UIScrollViewPanGestureRecognizer, which is part of the private API, but it's a subclass of UIPanGestureRecognizer so the above works fine. 滚动视图实际上会产生一个UIScrollViewPanGestureRecognizer,它是私有API的一部分,但它是UIPanGestureRecognizer的子类,所以上面的工作正常。

To support iOS6 or below, then you'll need to loop through the gestureRecognizers of the UIScrollView, detect which one is a UIPanGestureRecognizer and perform the requireGestureRecognizerToFail selector on your UILongPressGestureRecogizer with that. 为了支持iOS6的或以下,那么你会通过的UIScrollView的gestureRecognizers需要循环,检测其中一个是UIPanGestureRecognizer并在您UILongPressGestureRecogizer与执行requireGestureRecognizerToFail选择。

your code seems to be fine,it should work i think.i used below code and its working fine for me. 你的代码似乎很好,它应该工作我认为。我使用下面的代码,它的工作正常。

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

and its method, 和它的方法,

- (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];
   } 
}

Here i took imageView as subview of scrollview as u said 正如你所说,我把imageView作为scrollview的子视图

Since your UIScrollView is the common parent, that's probably where your gesture recognizer needs to be. 由于您的UIScrollView是常见的父级,这可能是您的手势识别器需要的位置。 You can determine which subview is being pressed by looking at the location of the point supplied in your action. 您可以通过查看操作中提供的点的位置来确定正在按下哪个子视图。 So, the individual subviews do not need gesture recognizers. 因此,各个子视图不需要手势识别器。

So, you would do something like this: 所以,你会做这样的事情:

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

So, then you have the view that was long-pressed. 那么,你就有了长期以来的观点。

Other things that could cause the action not to fire would be a delegate problem or if the scroll is contained by another view that is intercepting the touch. 其他可能导致操作无法触发的事情将是委托问题,或者如果滚动包含在另一个拦截触摸的视图中。

HTH HTH

Instead of 代替

 [scroll addGestureRecognizer:longPress]; 

Add the gesture on your subviews, right after you declare them and before you add them to scrollview 在您声明它们之后以及将它们添加到scrollview之前,在子视图上添加手势

 [subview addGestureRecognizer:longPress]; 

Woohoo it works! 哇哇它有效!

The problem was: 问题是:

imgContainer was a UIView with an empty frame with several UIImageViews as subviews imgContainer是一个带有空框架UIView,其中有几个UIImageViews作为子视图

I was under the impression that as I added a subview to imgContainer, imgContainer would expand . 的印象是,当我向imgContainer添加子视图时,imgContainer会扩展

This is not true . 事实并非如此

I had to set imgContainer's frame to the same content frame as the scroll view and then everything became ok. 我必须将imgContainer的框架设置为与滚动视图相同的内容框架 ,然后一切都变得正常。

I hope this answer helps any other future iOS firs timers like me. 我希望这个答案可以帮助像我这样的未来iOS第一次定时器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM