三重嵌套 UIScrollView 分页问题

发布于 2024-12-17 14:30:19 字数 512 浏览 0 评论 0原文

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

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

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

任何帮助或建议将不胜感激。

Backstory

I have an iPad app that needs to allow the user to navigate through groups of images. Each group is laid out in its own vertical UIScrollView (paged) so the user can swipe up and down down to see each image. Each of the group UIScrollViews is placed in a single (only one exists in the app) outer horizontal UIScrollView (also paged). This works great.... I can swipe up and down to view the images in a group and swipe left and right to go to the next or previous group.

Problem

The problem started when I needed to add zooming for each image. I accomplished this by placing each image inside its own UIScrollView. When the image is zoomed I can pan around the image and when I get to the top or the bottom of the zoomed image the group's vertical UIScrollView pages to the next or previous image as expected. Unfortunately the outer horizontal scrollview will not page to the next group when the image is zoomed and I pan to the leftmost or rightmost edge.

Is there a better(more correct) approach than triple nesting UIScrollViews or can I somehow forward touches to the outer horizontal scrollview?

Any help or suggestions would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薄情伤 2024-12-24 14:30:19

希望我还不算太晚,但我想我有办法解决你的问题。

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

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

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

我还留下了一些彩色边框,以便我可以轻松地看到每个滚动视图如何滚动。

  • 洋红色 = 水平滚动视图
  • 白色 = 垂直滚动视图
  • 蓝色 = 图像滚动视图(包含图像并允许缩放的滚动视图)
  • 红色 = UIImageView

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

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

最后,我想说这种浏览方式对我来说有点奇怪,因为我有时会向不想要的方向滚动。我经常认为我垂直滑动手指只是为了发现滚动视图向左或向右移动,因为它解释了我的一些微小的水平移动。

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

编辑:

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

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

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

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

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

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

编辑 2013

天啊,这些滚动视图真是绝妙的东西:(

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

在应用程序内部,有一个可以使用的开关在有/没有修复的情况下进行测试。

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

如果没有修复,一旦您到达具有最内部滚动视图的页面,您就会几乎卡在那里,因为垂直滚动手势不会转发到最外部滚动。

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

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

PS:我还没有测试缩放会发生什么,但我看不出为什么这个方法不应该工作(或适应工作)。

hope i'm not too late but I think I have a solution for your problem.

Here you can find an Xcode project demonstrating the scrollview setup you have, your problem and the proposed solution: https://bitbucket.org/reydan/threescrollviews

Basically the solution was to add 1 pixel to the contentSize.width of the vertical scrollviews. This forces the vertical scrollview to scroll a little when you pan to the edge of the zoomed image. It scrolls a little and then continues to the next vertical scrollview.

If you download the project you will see that I've created some scrollviews in the viewDidLoad method. There, I create one horizontal scrollview containing 3 vertical scrollviews, each containing 5 images. Each image is actually incapsulated in a scrollview to enable per-image zooming. In total... triple nested scrollviews.

I've also left some colored borders so that I can easily see how each scrollview scrolls.

  • the magenta = horizontal scrollview
  • the white = vertical scrollview
  • the blue = the image scrollview (the one that contains the image and allows for zooming)
  • the red = the UIImageView

You will see that I've tagged each image scrollview with value 10. This is used in the implementation of - (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView delegate method where I return nil unless the event came from one of the image scrollviews.

If you have any questions about the project I made feel free to ask.

In the end, I would like to say that this browsing method is a little quirky for me as I sometimes scroll in the unwanted direction. Often I think I flick my finger vertically only to find the scrollview going left or right because it interpreted some tiny horizontal movement I had.

The problem I found with paging enabled for both horizontal and vertical movement is that the scrollviews are direction-locked, or so it seemed to me.

EDIT:

Today I've investigated the problem even more. These are my conclusions:

  • it's not a problem with zooming, it's a problem with having larger content in the innermost scrollview than the visible area(you can try this by zooming or simply initializing the content size larger than the bounds). This enables panning inside the inner-most scrollview and completely changes the behaviour of the touch events.

  • the bounce for a scrollview flag affects the behaviour of the panning(dragging) gesture when it reaches the edges of the content. If bounces=false then your panning gesture will stop at the edge, not forwarding the drag event up the chain (and thus not scrolling the parent scrollviews to show you other images). If bounces=true then, when you reach the edge and continue to drag the events will be forwarded to the parent scrollview and that scrollview will also be dragged. However, I've found that the dragging while bouncing reduces the distance dragged by aproximately 50%. This also happens in the Photos app.

  • if you start the dragging while the innermost scrollview is at the edge of the content then the scrollview is smart and will forward all events to the parent scrollview.

  • for some reason, triple nested scrollviews are problematic as the events are simply not forwarded between the topmost and middle scrollviews while panning inside the innermost scrollview. I have no idea why.

My solution with that +1 pixel to the content size, partially solves the problem.

EDIT 2013

Boy, these scrollviews are something out of this world :(

After more than a year of searching (just kidding... it was actually 2 days) I think I found a good elegant solution to the triple nested scrollviews.
I created a test project here:
https://github.com/reydanro/TripleNestedScrollViews

Inside the app, there is a switch which you can use to test with/without the fix.

The setup I am using in my app is a little different than this question. I have 1 vertical paged scrollview. Inside it, I have multiple horizontal paged scrollviews.
Inside some of the horizontal scrollviews I have another vertical paged scrollview.

Without the fix, once you get to the page with the inner-most scrollview you are pretty much stuck there as the vertical scrolling gestures are not forwarded to the outer-most scroll.

The fix is a custom UIGestureRecognizer that you need to add to the inner-most scrollviews. This recognizer follows touch events and if it detects a drag beyond the contentArea, then it will temporarily disable the rest of the scrollview's recognizers. This is the only method I discovered to make the scrollview forward the events up the chain

The gesture recognizer code is very rough with limited customization but should get the job done. At the moment I am focused on the app I develop, but will continue to update the repository.

PS: I haven't tested what happens with zoom but I see no reason why this method should not work (or be adapted to work).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文