三重嵌套UIScrollView分页问题

时间:2011-11-22 16:12:30

标签: ios ipad uiscrollview zooming

背景故事
我有一个iPad应用程序,需要允许用户浏览图像组。每个组都在其自己的垂直UIScrollView(分页)中布局,因此用户可以向上和向下滑动以查看每个图像。每个组UIScrollViews都放在一个单独的(只有一个存在于应用程序中)外部水平UIScrollView(也是分页)。这很有用....我可以上下滑动以查看组中的图像,然后向左和向右滑动以转到下一组或上一组。

问题
当我需要为每个图像添加缩放时,问题就出现了。我通过将每个图像放在自己的UIScrollView中来实现这一点。当图像被缩放时,我可以平移图像,当我到达缩放图像的顶部或底部时,组的垂直UIScrollView页面按预期页面到下一个或上一个图像。不幸的是,当图像被缩放并且我平移到最左边或最右边时,外部水平滚动视图将不会翻页到下一组。

是否有比三重嵌套UIScrollView更好(更正确)的方法,还是可以以某种方式将触摸转发到外部水平滚动视图?

非常感谢任何帮助或建议。

1 个答案:

答案 0 :(得分:8)

希望我不会太迟,但我认为我的问题有解决方案。

在这里,您可以找到一个Xcode项目,展示您拥有的滚动视图设置,您的问题和建议的解决方案:https://bitbucket.org/reydan/threescrollviews

基本上解决方案是在垂直滚动视图的contentSize.width中添加1个像素。当您平移到缩放图像的边缘时,这会强制垂直滚动视图滚动一点。它会滚动一点,然后继续下一个垂直滚动视图。

如果您下载项目,您会看到我在viewDidLoad方法中创建了一些滚动视图。在那里,我创建了一个包含3个垂直滚动视图的水平滚动视图,每个包含5个图像。实际上,每个图像都在滚动视图中封装,以实现每个图像的缩放。总共...三重嵌套滚动视图。

我还留下了一些彩色边框,以便我可以轻松查看每个滚动视图的滚动方式。

  • magenta = horizo​​ntal scrollview
  • white = vertical scrollview
  • 蓝色=图像滚动视图(包含图像并允许缩放的图像)
  • 红色= UIImageView

您将看到我已使用值10标记每个图像scrollview。这用于- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView委托方法的实现,其中我返回nil,除非事件来自其中一个图像滚动视图。

如果您对该项目有任何疑问,请随时提出。

最后,我想说这种浏览方式对我来说有点古怪,因为我有时会向不想要的方向滚动。通常我认为我垂直地弹动我的手指只是为了找到向左或向右滚动视图,因为它解释了我的一些微小的水平运动。

我发现启用水平和垂直移动分页的问题是滚动视图是方向锁定的,或者在我看来是这样。

修改

今天我更进一步调查了这个问题。这些是我的结论:

  • 它不是缩放的问题,在最里面的滚动视图中拥有比可见区域更大的内容的问题(您可以通过缩放或简单地初始化大于的内容大小来尝试此问题界限)。这样可以在最里面的滚动视图中进行平移,并完全改变触摸事件的行为。

  • 滚动视图标记的反弹会影响到达内容边缘时平移(拖动)手势的行为。如果bounces=false那么您的平移手势将停在边缘,不会将拖动事件转发到链上(因此不会滚动父滚动视图以显示其他图像)。如果bounces=true那么,当您到达边缘并继续拖动时,事件将被转发到父滚动视图,并且还将拖动该滚动视图。但是,我发现在弹跳时拖动可以减少大约50%的距离。这也发生在照片应用程序中。

  • 如果您开始拖动,而最里面的scrollview位于内容的边缘,那么scrollview是智能的,并将所有事件转发到父滚动视图。

  • 出于某种原因,三重嵌套滚动视图是有问题的,因为在最里面的滚动视图内平移时,事件不会在最顶层和中间滚动视图之间转发。我不明白为什么。

我的解决方案使用+1像素的内容大小,部分解决了问题。

编辑2013

男孩,这些滚动视图不属于这个世界:(

经过一年多的搜索(开玩笑......实际上是2天)我觉得我找到了一个很好的优雅解决方案来实现三重嵌套的滚动视图。 我在这里创建了一个测试项目: https://github.com/reydanro/TripleNestedScrollViews

在应用程序内部,有一个开关可用于测试是否有修复。

我在我的应用中使用的设置与此问题略有不同。我有1个垂直分页滚动视图。在它里面,我有多个水平分页滚动视图。 在一些水平滚动视图中,我有另一个垂直分页滚动视图。

没有修复,一旦你到达最里面的滚动视图的页面,你就会被困在那里,因为垂直滚动手势不会被转发到最外面的滚动。

修复是您需要添加到最里面的滚动视图的自定义UIGestureRecognizer。此识别器跟踪触摸事件,如果它检测到contentArea之外的拖动,则它将暂时禁用其余的scrollview识别器。这是我发现的唯一方法,使scrollview将事件向上转发到链

手势识别器代码非常粗糙,定制有限,但应该完成工作。目前我专注于我开发的应用程序,但将继续更新存储库。

PS:我还没有测试过缩放会发生什么,但我认为没有理由不采用这种方法(或适应工作)。