这可能适用于 swift。它在 iOS 7.1 中对我有用。没有 swift 的 Xcode 5.1.1。
答案来自:
ScrollView not scrolling when dragging on buttons
先决条件:UIScrollView 子类,Xcode 5.1.1,iOS 7.1.,UIButton 在 UISV 滚动时保持在固定位置,UISV 中的一些按钮添加为子视图
理论:
-在 UISCV 子类实现的 .m 文件中:
- (void)layoutSubviews
{
NSLog(@" layoutSubviews - contentOffset.x = %f ",self.contentOffset.x);
}
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInView:self];
NSLog(@" touchesShouldBegin - Toched point - (%f,%f) -",positionInScene.x,positionInScene.y);
return YES;
}
如果您现在将您的 SV 滚动到按钮框架(您已添加)之外,您将看到 layoutSubview 方法被调用并更改了您滚动的 contentOffset 位置。我使用了 .x 坐标,因为我使用了水平滚动(如果您有垂直滚动,请使用 .y)。然而,如果你点击你的按钮,你会看到 touchesShouldBegin 被调用,正确的触摸位置是你按下按钮。但是,如果您将手指放在按钮上并尝试拖动,则不会发生滚动,也不会调用 layoutSubviews。这是问题所在。现在你将拥有你的触摸,但不是你的滚动。您拥有的按钮越多,“滚动机会”就越少,因为每次触摸都会停止滚动。
解决方案 1 - 部分
如果您在 touchesShouldBegin 中返回 NO,即使按钮被触摸,您也可以滚动,但不会像 docs(CTRL + F "touchesShouldBegin") 中所写的那样注册触摸事件
返回值 如果不希望滚动视图发送事件,则返回 NO
要查看的消息。如果您希望查看接收这些消息,请返回
是(默认)。
因此,您的滚动视图不会注册任何触摸事件。在这个link
有人提议制作 UIImageViews 而不是按钮并使用它们的帧大小。使用帧大小,您可以检查 positionInScene (CGPoint) 是否适合任何帧,以及它是否确实调用了使您的按钮起作用的方法。
解决方案 2 - 完全
1.添加:
self.canCancelContentTouches = YES;
在 init 方法中添加到您的子类 UISV .m 文件。
2.添加:
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
return YES;
}
到您的子类 UISV .m 文件。
如果你现在运行你的应用程序,你会看到在一个按钮触摸时 layoutSubviews 和 touchesShouldBegin 都被调用了。滚动有效。它可以工作,但仍然不会调用按钮的方法。原因是 touchEvent 被取消,并且在取消触摸后允许跟踪。阅读docs (CTRL + F "canCancelContentTouches"):
如果此属性的值为 YES 并且内容中的视图具有
开始跟踪触摸它的手指,如果用户拖动手指
足以启动滚动,视图会收到一个
touchesCancelled:withEvent: 消息和滚动视图处理
像滚动一样触摸。如果该属性的值为 NO,则滚动
一旦内容显示,无论手指移动,视图都不会滚动
视图开始跟踪。
由于您将按钮设置为:
[myButton addTarget:self action:@selector(myButtonPressed:) forControlEvents:UIControlEventTouchUpOutside];
myButtonPressed 将不会被调用,因为 UIControlEventTouchUpOutside 发生了。如果您将其更改为:
[flagButton addTarget:self action:@selector(myButtonPressed:) forControlEvents:UIControlEventTouchCancel];
并再次运行代码,您不仅可以滚动,还可以单击按钮并进一步滚动,因为您的按钮现在会在发生 EventTouchCancel 时调用选择器,因为您允许 UISV 将 touchBegin 转换为 touchCancelled :
self.canCancelContentTouches = YES;
不要忘记覆盖(添加):
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
return YES;
}
没有它就行不通。请提供任何反馈,因为我希望这将很快起作用,我将很快开始使用。希望它有所帮助。 Gl & hf :)