【问题标题】:UIScrollView image/photo viewer with paging enabled and zooming启用分页和缩放的 UIScrollView 图像/照片查看器
【发布时间】:2010-11-01 19:41:59
【问题描述】:

好的,我认为是时候在互联网上为这个问题建立一个官方位置了:How to make a UIScrollView photoviewer with paging and zooming。欢迎我的同胞UIScrollView黑客。

我有一个启用了分页的UIScrollView,我正在显示UIImageViews,就像内置的照片应用程序一样。 (这听起来是不是很熟悉?)

我在github上找到了以下项目:

https://github.com/andreyvit/ScrollingMadness/wiki

这显示了如何在启用分页时在滚动视图中实现缩放。如果其他人尝试这样做,我实际上必须删除 UIScrollView 子类并使用本机类,否则它不起作用。我认为这是因为 3.0 SDK 中有关滚动视图如何拦截触摸事件的更改。

所以想法是在开始缩放时删除所有其他视图,并将当前视图移动到 scrollview 中的 (0, 0),更新 contentsize 等。然后当您缩放回 1.0 f 它将其他视图添加回来并将所有内容恢复原状。

无论如何,该项目在模拟器中运行良好,但在设备上,您正在调整大小的视图有一些令人讨厌的移动,这看起来是由于我们正在更改 contentsize/offset 等事实造成的。用于调整大小的视图。您必须移动此视图,否则您可以通过其他视图留下的空白向左平移。

我在3.0 SDK release notes的“已知问题”中发现了一个有趣的注释:

UIScrollView:缩放后,内容插入被忽略,内容留在错误的位置。

这听起来像是这里正在发生的事情。放大后,由于您更改了偏移等,视图将移出屏幕。

我已经在这方面花费了几个小时,但我正在慢慢意识到这根本行不通。

Three20 的照片查看器是不可能的:它太重了,而且有太多不必要的 UI 和其他行为。

内置的照片应用似乎有一些魔力。如果您放大图像并平移到远边缘,则当前照片会独立于旁边的照片移动,这不是您在使用标准 UIScrollView 时所得到的。

我看过关于嵌套UIScrollView 的讨论,但我真的不想去那里。

有没有人用标准的UIScrollView 管理过这个(并且在 2.2 和 3.0 SDK 中工作)?我不喜欢滚动自己的缩放 + 弹跳 + 平移 + 分页代码。

【问题讨论】:

  • 作为 ZoomScrollView 的作者,我正在基于嵌套滚动视图开发与 3.0 SDK 兼容的更新版本。运行后会在此处回复。
  • 我还注意到,如果您稍微缩放一下,松开,然后再次开始缩放,就不会出现错误的翻转/移动。令人沮丧。
  • 3.0 中破坏 ScrollingMadness 代码的更改的目的正是为了允许嵌套滚动视图。所以理论上,内置照片应用程序的行为应该在 3.0 中更加直接。
  • 嗯,我已经通过嵌套 UIScrollViews 几乎解决了 3.0 的问题,尽管我不太确定它是如何神奇地工作的。问题是我也需要代码在 2.2+ 上工作,并且没有合理的方法让它在两者上工作。有时间我会尝试抛出一些代码。
  • 我认为如果不编写自己的滚动视图,您将无法获得在 2.2 和 3.0 上运行的单个代码库。在 3.0 中,传递事件的方式发生了很大变化。

标签: ios iphone uiscrollview


【解决方案1】:

更新

因为下面的消息,我删除了之前的回答...

对于那些没有听说过的人来说是个大新闻。 Apple 已向 iphone 开发者计划的所有成员发布了 2010 年 WWDC 会议视频。讨论的主题之一是他们如何创建照片应用程序!!!他们逐步构建了一个非常相似的应用程序,并免费提供了所有代码。

它也不使用私有 api。这是示例代码下载的链接。您可能需要登录才能获得访问权限。

Check This

还有,这里是 iTunes WWDC 页面的链接:

Check This

【讨论】:

  • 对于那些不想浏览所有会话和示例代码的人,您正在寻找会话 104,使用滚动视图设计应用程序。
  • 我刚刚看完了会议视频并浏览了示例代码,这真是个好东西。我的一个抱怨是:使用CATiledLayer 获得出色性能和低内存使用的最终目标需要将图像预处理成图块。充其量,这可能非常不方便。
  • 我同意。显然,他们为“照片”应用找到了解决此问题的方法。它可以动态平铺图像,也可以通过其他方式处理大图像。
  • 请注意,将图像切割成图块并为给定缩放级别正确命名只是 ImageMagick 的一行命令:stackoverflow.com/questions/3245351/iphone-tiling-an-image
  • 是的,他们希望每张图片都是一张图片,可能分辨率很高,他们使用 CATiledLayer 并在一些绘图代码中生成图块。
【解决方案2】:

我编写了一个简单易用的照片浏览器,名为MWPhotoBrowser。我决定创建它,因为 Three20 太重/臃肿,因为我只需要一个照片查看器。

MWPhotoBrowser 可以通过提供 UIImage 对象或文件、网络图像或库资源的 URL 来显示一个或多个图像。照片浏览器无缝地处理来自网络的照片的下载和缓存。照片可以缩放和平移,并且可以显示可选(可自定义)的标题。浏览器还可用于允许用户使用网格或主图像视图选择一张或多张照片。

【讨论】:

  • 我还想知道一件事...它仅从第一张图像开始,我应该更改的位置,以便我可以从所选图像开始查看图像????
  • 我无话可说,但感谢所有优秀的开发人员,他们选择与大家分享您的出色工作。谢谢一百万!
  • 如何更改 MWPhotobrowser 的宽度?实际上我想在宽度为 500 的 iPad 上使用它。
【解决方案3】:

您说您已经看到有关嵌套 UIScrollViews 的讨论,但不想去那里 - 但这是要走的路!它运行起来既简单又好用。

这基本上就是 Apple 在其 PhotoScroller 示例中所做的(以及 Jonah 的回答中链接到的 2010 WWDC 演讲)。仅在这些示例中,他们添加了一大堆复杂的平铺和其他内存管理。如果您不需要平铺等,并且如果您不想涉足这些示例并尝试删除与之相关的位,那么嵌套 UIScrollViews 的基本原理实际上非常简单:

  • 创建一个外部 UIScrollView 并设置它的 pagingEnabled = true。将其添加到主视图,并将其宽度和高度设置为主视图的宽度和高度。

  • 根据需要创建尽可能多的内部 UIScrollView。将它们的宽度和高度设置为主视图的宽度和高度。将它们作为子视图添加到您的外部 UIScrollView,每个相邻,从左到右。

  • 将外部 UIScrollView 的内容大小设置为所有内部 UIScrollView 的并排宽度的总和(等于 [您的主视图的宽度]*[图像数量])。

  • 将图像的 UIImageViews 添加到内部 UIScrollViews,一个 UIImageView 到每个内部 UIScrollView。将每个 UIScrollView 的内容大小设置为每个 UIImageView 的大小。

  • 为每个内部 UIScrollView 设置最小和最大缩放比例,并将每个内部 UIScrollView 的委托设置为您的视图控制器。在委托的 viewForZoomingInScrollView 中,为传递的 UIScrollView 返回相应的 UIImageView。 (为此,只需将每个 UIImageViews 保存在 NSArray 中,并将相应的 UIScrollView 的 tag 属性设置为相应 UIImageView 的索引。然后您可以读取传递给 viewForZoomingInScrollView 的 UIScrollView 中的标签,并从 NSArray 返回相应的 UIImageView) .

就是这样。就像照片应用程序一样工作。

如果你有很多照片,为了节省内存,你可以只拥有两个内部 UIScrollView 和两个 UIImagesView。然后,您可以在它们之间动态翻转,在外部 UIScrollView 中移动它们的位置,并在用户滚动外部 UIScrollView 时更改它们的图像。稍微复杂一点,但原理是一样的。

【讨论】:

  • 是的,嵌套滚动视图现在可以正常工作。当我最初发布这个问题时,对 iOS 3.2 的支持很重要,但是嵌套滚动视图有各种各样的问题。
  • 想你现在可能已经解决了!但这些老问题一直停留在 Google 搜索结果的顶部,因此认为值得添加。
  • 到目前为止,这个答案值得更多的投票:我刚刚使用嵌套滚动视图(在 iOS 6 上)用几行代码解决了整个问题。
  • stackoverflow.com/questions/32857144/… 。有什么帮助吗?
【解决方案4】:

我玩了一些原生照片应用程序,我想我可以自信地说他们使用的是单个 UIScrollView。赠品是这样的:放大图像,然后向左或向右拉。您将看到下一张或上一张照片。如果你用力拉,它甚至会以 1.0f 变焦翻页到下一张照片。向后翻转,之前缩放的照片也会恢复到 1.0f 缩放。

显然我没有编写 Photos.app,但我会大胆猜测他们是如何做到的:

  • 一个 UIScrollView 和一个 UIScrollViewDelegate
  • 用 UIImageView 子级填充 UIScrollView
  • 收听scrollViewDidScroll:
  • Do some math 并找出您当前所在的页面
  • 收听viewForZoomingInScrollView:
  • 根据页面索引返回不同的视图
  • 收听scrollViewDidEndZooming:withView:atScale: 并根据内容选择做一些抗锯齿等

如果您决定尝试一下,请告诉我效果如何。我很想知道你最终是如何让这个工作的。更好的是,将它发布到github。

【讨论】:

    【解决方案5】:

    我做了一些玩弄 本机照片应用程序,我想我可以 自信地说他们正在使用 单个 UIScrollView。赠品是 这:放大图像,然后拉到 左边或右边。你会看到 下一张或上一张照片。如果你拉 够难的,它甚至会分页到 下一张 1.0f 变焦的照片。向后翻转并 之前放大的照片将是 也回到 1.0f 缩放。

    这是错误的。我正在使用嵌套滚动视图,并获得完全相同的效果。如果您正在使用一些内存管理方案(我必须开始使用......我的页码相当高('在 2 个滚动视图中每个大约 50 个)),那么您可以使用类似于触发页面的任何机制加载/卸载以从当前页面触发页面 -1 和 +1 的缩放重置。

    我怀疑苹果会在上一张照片消失后立即启动此功能。

    我不明白的是如何实现页面之间的平滑滚动——在转换的那一刻总是有一个很短的挂起。不明白。我已经非常深入地修复它 - NSInvocationOperations 是我的第一站,然后我为页面视图(保留其图像视图)创建了一个可重用的视图队列......仍然是这个死机。

    我只运行了一个 NSOperationQueue,并且我尝试过调整最大并发操作数。我的想法是主线程被竞争队列阻塞,或者甚至一个队列试图做很多事情......仍然是挂起。

    我什至尝试创建我的媒体的超低质量版本,以防出现问题。每张图像的重量约为 10k(这些是 jpeg,请注意)......你猜对了。问题仍然存在。

    我已经下定决心要做我以前做过的事情,并使用 Three20 的 TTPhotoViewController。我花了几个小时浏览该代码,这总是一种很好的教育。不过,在这一点上,我真的很想知道这到底是从哪里来的,如果只是这样我就可以度过我无法入睡的几个小时,想知道一些不那么大脑沸腾的事情。

    【讨论】:

      【解决方案6】:

      如果苹果在 SDK 中内置了一个像照片应用程序这样的图像查看器供我们使用,那肯定会很好。我目前正在使用three20,效果很好。但是,当您真正想要的只是照片查看器时,需要携带很多额外的东西。

      【讨论】:

        【解决方案7】:

        我为此写了一个代码,可以作为参考

        1. 加载当前视图滚动视图和图像视图.. 而对于当前视图旁边的屏幕,只有图像视图

        2. 在当前页面加载时删除所有视图以节省内存,这对许多照片项目都有好处

        3. 使用标签区分不同的scrollview

        _xxxxxxx

        the download link click here

        【讨论】:

          【解决方案8】:

          【讨论】:

          • 就像我在 OP 中所说的,Three20 的照片查看器是不可能的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-06-09
          • 2016-03-30
          • 1970-01-01
          • 1970-01-01
          • 2018-04-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多