我正在开发一个应用程序,其中有几个UIView对象,它们是UIScrollView对象的子视图。我以编程方式创建子视图,并根据关联对象的属性将它们放在滚动视图中。允许用户在滚动视图上移动这些子视图。通常情况下,这是可行的,但有时滚动视图抓住潘手势。
如果触摸位置在子视图中,我想要做的是禁止滚动视图手势识别器。
通过查看滚动视图的手势识别器数组并查找UIScrollViewPanGestureRecognizer
对象,我可以找到滚动视图手势识别器。我想只有一个。
我的一个想法是让我的视图控制器成为这个手势识别器的委托,如果触摸在子视图的范围内,那么委托就会抑制它。
这是处理这种情况的最好方法,还是有更好的方法?
我做过类似的事情,在我对我自己的问题的回答中描述了这一点。How to get stepper and longpress to coexist?
嗯。看起来,它将比我预期的更难识别滚动视图的UIScrollViewPanGestureRecognizer
。任何关于这样做的提示都将不胜感激。
我的主意行不通。为了编码我的想法,我不得不让我的VC代表滚动视图的pan手势识别器。但是,当我这样做时,我会得到以下错误:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UIScrollView's built-in pan gesture recognizer must have its scroll view as its delegate.'
这是我使用的代码。在viewDidLoad
中,我调用了一个方法,该方法获取滚动视图的pan手势识别器并将self设置为委托(self.scrollViewPanGestureRecognizer
只是存储它的一个属性):
self.scrollViewPanGestureRecognizer = [self.scrollView panGestureRecognizer];
self.scrollViewPanGestureRecognizer.delegate = self;
然后,我实现了这个委托方法:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//Disable touch if touch location is in a subview.
BOOL enableGestureRecognizer = YES;
if (gestureRecognizer == self.scrollViewPanGestureRecognizer) {
CGPoint touchLocation = [touch locationInView:self.scrollView];
for (UIView *s in self.scrollView.subviews) {
if (CGRectContainsPoint(s.frame, touchLocation)) {
enableGestureRecognizer = NO;
}
}
}
return enableGestureRecognizer;
}
这似乎是个好主意,但看来我不能让我的风投成为代表。
刚在滚动视图上尝试将scrollEnabled
设置为NO
。它成功地禁用了滚动,但没有解决问题。视图仍然偶尔不会对手势做出反应。考虑到可能是某些bug导致手势识别器从对象中掉下来,我要求调试器为有问题的视图显示手势识别器。他们还在那里。我很困惑。
更新:新信息。我终于意识到,没有响应的子视图是屏幕右侧的子视图。经过仔细的测试,这似乎只发生在景观方向,只有当手指位置是在右边的边缘描绘,即320点。显然,当旋转到景观时,某些东西没有被处理。每件事看起来都很正常,但是手势没有被识别出来。
只是为了保持笑容,我决定在方法viewDidLayoutSubviews
中显示框架、边界和内容区域。我得到的是:
self.view.frame is {{0, 0}, {480, 320}}
self.view.bounds is {{0, 0}, {480, 320}}
self.scrollView.frame is {{0, 0}, {480, 320}}
self.scrollView.bounds is {{0, 0}, {480, 320}}
self.scrollView.contentSize is {480, 320}
我好像漏掉了什么。旋转时还需要设置什么?
发布于 2014-02-04 03:51:13
我找到了解决办法。我忘记了子视图不是直接放置在滚动视图中的。有一个视图最初占据了放置子视图的滚动视图的范围。层次结构如下:
self.view
scroll view
UIView (fills whole scroll view)
subview1
subview2
subviewn
在处理旋转的代码中,我没有调整放置子视图的UIView的大小。纠正这个问题解决了这个问题。
我最初尝试在它们和滚动视图之间放置没有UIView超级视图的子视图,但是由于某些原因,它没有工作。增加这个额外的层解决了这个问题,但我忘记了旋转时的调整。
因此,我猜手势识别器没有响应,因为虽然它们是可见的,但它们超出了其superview的范围。
发布于 2014-02-03 06:09:11
使用requireGestureRecognizerToFail
:方法。
当其中一个手势发生在其(scrollViewGesture)上时,您希望滚动视图pan手势subView失败。
因此,当您将pan手势添加到您的(subViewGesture),中时,在属性下面设置为
scrollViewGesture.requireGestureRecognizerToFail =subViewGesture;
发布于 2014-02-03 15:03:27
我给出了一个社区wiki的答案,因为我还没有完全想出这个解决方案。主要是从文档中利用这一点:
子类可以覆盖
touchesShouldBegin:withEvent:inContentView:
、pagingEnabled
和touchesShouldCancelInContentView:
方法(滚动视图调用这些方法),以影响滚动视图处理滚动手势的方式。
https://stackoverflow.com/questions/21520437
复制相似问题