Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/115.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 允许UIScrollView及其子视图同时响应触摸_Ios_Uiscrollview_Uigesturerecognizer_Touches - Fatal编程技术网

Ios 允许UIScrollView及其子视图同时响应触摸

Ios 允许UIScrollView及其子视图同时响应触摸,ios,uiscrollview,uigesturerecognizer,touches,Ios,Uiscrollview,Uigesturerecognizer,Touches,我希望UIScrollView及其子视图都能接收子视图中的所有触摸事件。每个人都能以自己的方式作出反应 或者,如果点击手势被转发到子视图,一切都会好起来 很多人都在这方面苦苦挣扎。以下是许多相关问题中的几个: 顺便说一句,如果我在滚动视图中覆盖hitTest:withEvent:,只要userInteractionEnabled是YES,我就会看到触摸。但这并不能真正解决我的问题,因为: 1) 在这一点上,我不知道这是不是水龙头。 2) 有时我需要将userInteractionEnabl

我希望UIScrollView及其子视图都能接收子视图中的所有触摸事件。每个人都能以自己的方式作出反应

或者,如果点击手势被转发到子视图,一切都会好起来

很多人都在这方面苦苦挣扎。以下是许多相关问题中的几个:



顺便说一句,如果我在滚动视图中覆盖hitTest:withEvent:,只要userInteractionEnabled是YES,我就会看到触摸。但这并不能真正解决我的问题,因为:

1) 在这一点上,我不知道这是不是水龙头。
2) 有时我需要将userInteractionEnabled设置为NO


编辑:为了澄清,是的,我想区别对待水龙头和平底锅。抽头应该由子视图处理。可以通过滚动视图以常规方式处理平移

如果您需要区分触摸和滚动,那么您可以测试触摸是否已移动。如果这是一个点击,那么touchHasbeenMove将不会被调用,那么您可以假设这是一个触摸

此时,您可以设置一个布尔值,以指示某个移动对象是否符合,并将此布尔值设置为其他方法中的一个条件


我正在路上,但如果这是你需要的,我以后会解释得更好

我不知道这是否能帮助您,但我遇到了一个类似的问题,我希望scrollview能够处理双击,但将单点转发到子视图。以下是
CustomScrollView

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

    UITouch* touch = [touches anyObject];
    // Coordinates
    CGPoint point = [touch locationInView:[self.subviews objectAtIndex:0]];

    // One tap, forward
    if(touch.tapCount == 1){
        // for each subview
        for(UIView* overlayView in self.subviews){
            // Forward to my subclasss only
            if([overlayView isKindOfClass:[OverlayView class]]){
                // translate coordinate
                CGPoint newPoint = [touch locationInView:overlayView];
                //NSLog(@"%@",NSStringFromCGPoint(newPoint));

                BOOL isInside = [overlayView pointInside:newPoint withEvent:event];
                //if subview is hit
                if(isInside){
                    Forwarding
                    [overlayView touchesEnded:touches withEvent:event];
                    break;
                }
            }
        }

    }
    // double tap : handle zoom
    else if(touch.tapCount == 2){

        if(self.zoomScale == self.maximumZoomScale){
            [self setZoomScale:[self minimumZoomScale] animated:YES];
        } else {
            CGRect zoomRect = [self zoomRectForScrollView:self withScale:self.maximumZoomScale withCenter:point];            

            [self zoomToRect:zoomRect animated:YES];
        }

        [self setNeedsDisplay];

    }
}
当然,应该更改有效代码,但此时您应该拥有决定是否必须转发事件所需的所有信息。您可能需要在另一个方法中实现它,如touchesMoved:withEvent:


希望这能有所帮助。

实现目标的一种不切实际的方法——并非100%准确——是对UIWindow进行子类化,并覆盖-(void)sendEvent:(UIEvent*)事件

一个简单的例子:

在SecondResponderWindow.h标题中

//SecondResponderWindow.h

@protocol SecondResponderWindowDelegate
- (void)userTouchBegan:(id)tapPoint onView:(UIView*)aView;
- (void)userTouchMoved:(id)tapPoint onView:(UIView*)aView;
- (void)userTouchEnded:(id)tapPoint onView:(UIView*)aView;
@end

@interface SecondResponderWindow : UIWindow
@property (nonatomic, retain) UIView *viewToObserve;
@property (nonatomic, assign) id <SecondResponderWindowDelegate> controllerThatObserves;
@end
它并不是100%符合您的期望-因为您的second responder视图没有通过-TouchDidBeagin:等本机处理触摸事件,并且必须实现SecondResponderWindowDelegate。不过,这种黑客确实允许您在其他响应者上处理触摸事件


此方法受MITHIN KUMAR的第一个免责声明的启发并从中得到扩展。如果在
UIScrollView
上将
userInteractionEnabled
设置为
NO
,则不会向子视图传递任何触摸事件。就我所知,除了一个例外,没有办法解决这个问题:在
UIScrollView
的superview上截取触摸事件,并专门将这些事件传递给
UIScrollView
的子视图。老实说,我不知道你为什么要这么做。如果您想禁用特定的UIScrollView功能(例如…嗯,滚动),您可以很容易地做到这一点,而无需禁用用户交互

如果我理解您的问题,您需要点击UIScrollView处理的事件,以及传递给子视图的事件?在任何情况下(无论手势是什么),我认为您要查找的是协议
UIGestureRecognitizerDelegate
中的协议方法。在子视图中,无论您有什么手势识别器,都要在手势识别器上设置一个委托(可能是任何类首先设置
UIGestureReconginzer
)。重写上述方法并返回
YES
。现在,该手势将与可能“窃取”该手势的任何其他识别器一起被识别(在您的情况下,是轻触)。使用此方法,您甚至可以微调代码,使其仅向子视图发送某些类型的手势,或仅在某些情况下发送手势。它给你很大的控制力。请务必阅读该方法,尤其是这一部分:

当用户识别手势时调用此方法 手势识别器或其他手势识别器都会阻止 其他手势识别器无法识别其手势。注意 返回YES保证允许同时识别; 另一方面,返回NO不能保证防止 同时识别,因为另一个手势识别器 代表可以返回YES


当然,这里有一个警告:这只适用于手势识别器。因此,如果您试图使用
touchesbeated:
touchesend
等来处理触摸,则可能仍然存在问题。当然,您可以使用
hitTest:
将原始触摸事件发送到子视图,但为什么呢?当您可以将
uigesturecognizer
附加到视图并免费获得所有功能时,为什么要在
UIView
中使用这些方法处理事件?如果您需要以任何标准
uigesturecognizer
都无法提供的方式处理触摸,请子类
uigesturecognizer
并在那里处理触摸。通过这种方式,您可以获得
UIgestureRecognitor
的所有功能以及您自己的自定义触摸处理。我真的认为苹果打算用
uigesturecognizer
取代开发者在
UIView
上使用的大部分(如果不是全部的话)定制触摸处理代码。它允许代码重用,并且在减轻代码处理触摸事件时更容易处理

我也遇到了同样的问题,但是在
UIPageViewController
中有一个scrollview,所以它的处理方式必须稍有不同

通过将
UIScrollView
上每个识别器的
cancelsTouchesInView
属性更改为false,我能够接收到对
UIPageViewController
内按钮的触摸

为此,我将此代码添加到
viewDidLoad

guard let recognizers = self.pageViewController.view.subviews[0].gestureRecognizers else {
     print("No gesture recognizers on scrollview.")
     return
}

for recognizer in recognizers {
    recognizer.cancelsTouchesInView = false
}

将userInteractionEnabled设置为NO并期望用户交互数据看起来像是一个打破宇宙的pa
guard let recognizers = self.pageViewController.view.subviews[0].gestureRecognizers else {
     print("No gesture recognizers on scrollview.")
     return
}

for recognizer in recognizers {
    recognizer.cancelsTouchesInView = false
}