ios 启用分页和缩放的 UIScrollView 图像/照片查看器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/975708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:00:29  来源:igfitidea点击:

UIScrollView image/photo viewer with paging enabled and zooming

iosiphoneuiscrollview

提问by Mike Weller

OK, I think it's time to make an official place on the internet for this problem: How to make a UIScrollViewphotoviewer with paging and zooming. Welcome my fellow UIScrollViewhackers.

好的,我认为是时候在互联网上为这个问题建立一个正式的位置:如何制作UIScrollView具有分页和缩放功能的照片查看器。欢迎我的UIScrollView黑客伙伴们。

I have a UIScrollViewwith paging enabled, and I'm displaying UIImageViewslike the built-in photos app. (Does this sound familiar yet?)

UIScrollView启用了分页功能,并且显示方式UIImageViews类似于内置照片应用程序。(这听起来是不是很熟悉?)

I found the following project on github:

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

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

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

Which shows how to implement zooming in a scroll view while paging is enabled. If anyone else tries this out, I actually had to remove the UIScrollViewsubclass and use the native class otherwise it doesn't work. I think it's because of changes in the 3.0 SDK relating to how the scroll view intercepts touch events.

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

So the the idea is to remove all the other views when you start zooming, and move the current view to (0, 0) in the scrollview, updating the contentsizeetc. Then when you zoom back to 1.0f it adds the other views back and puts things all back in order.

因此,我们的想法是在开始缩放时删除所有其他视图,并将当前视图移动到 (0, 0) 中scrollview,更新contentsize等。然后当您缩放回 1.0f 时,它将其他视图添加回来并放置一切都恢复了秩序。

Anyway, that project works perfectly in the simulator, but on the device there is some nasty movement of the view you are resizing, which looks like it's caused by the fact we are changing the contentsize/offsetetc. for the view being resized. You have to do this view moving otherwise you can pan left through the whitespace left by the other views.

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

I found one interesting note in the "Known Issues" of the 3.0 SDK release notes:

我在3.0 SDK 发行说明的“已知问题”中发现了一个有趣的说明

UIScrollView: After zooming, content inset is ignored and content is left in the wrong position.
UIScrollView:缩放后,内容插入被忽略,内容留在错误的位置。

This kind of sounds like what is happening here. After zooming in, the view will shift offscreen because you have changed the offset etc.

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

I've spent hours on this already and I'm slowing coming to the sad realization that this just isn't going to work.

我已经在这方面花费了数小时,但我正在缓慢地意识到这行不通。

Three20's photo viewer is out of the question: it's too heavy weight and there is too much unnecessary UI and other behaviour.

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

The built in Photo app seems to do some magic. If you zoom in on an image and pan to the far edges, the current photo moves independently of the photo next to it which isn't what you get when trying this with a standard UIScrollView.

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

I've seen discussion about nesting the UIScrollView's but I really don't want to go there.

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

Has anybody managed this with the standard UIScrollView(and works in the 2.2 and 3.0 SDK)? I don't fancy rolling my own zoom + bounce + pan + paging code.

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

采纳答案by Jonah

UPDATE

更新

I deleted my previous answer because of the news below...

因为下面的新闻,我删除了我以前的答案...

Big news for those who haven't heard. Apple has released the 2010 WWDC session videos to all members of the iphone developer program. One of the topics discussed is how they created the photos app!!! They build a very similar app step by step and have made all the code available for free.

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

It does not use private api either. Here is a link to the sample code download. You will probably need to login to gain access.

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

Check This

检查这个

And, here is a link to the iTunes WWDC page:

而且,这里是 iTunes WWDC 页面的链接:

Check This

检查这个

回答by Michael Waterfall

I've written a simple and easy to use photo browser called MWPhotoBrowser. I decided to create it as Three20 was too heavy/bloated as all I needed was a photo viewer.

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

MWPhotoBrowser can display one or more images by providing either UIImage objects, or URLs to files, web images or library assets. The photo browser handles the downloading and caching of photos from the web seamlessly. Photos can be zoomed and panned, and optional (customisable) captions can be displayed. The browser can also be used to allow the user to select one or more photos using either the grid or main image view.

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

MWPhotoBrowser Screenshots

MWPhotoBrowser 截图

回答by delany

You say you've seen discussions of nesting UIScrollViews but don't want to go there - but that is the way to go! It works easily and well.

你说你已经看到了关于嵌套 UIScrollViews 的讨论但不想去那里 - 但这是要走的路!它工作轻松,效果很好。

It's essentially what Apple does in its PhotoScroller example (and the 2010 WWDC talk linked to in Jonah's answer). Only in those examples, they've added a whole bunch of complex tiling and other memory management. If you don't need the tiling etc. and if you dont want to wade through those examples and try and remove the bits related to it, the underlying principle of nesting UIScrollViews is actually quite simple:

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

  • Create an outer UIScrollView and set its pagingEnabled = true. Add it to your main view and set its width and height to your main view's width and height.

  • Create as many inner UIScrollViews as you want images. Set their width and height to your main view's width and height. Add them as subviews to your outer UIScrollView, each one next to the other, left to right.

  • Set the content size of the outer UIScrollView to the total of the widths of all the inner UIScrollViews side by side (which is equal to [your main view's width]*[number of images]).

  • Add your images' UIImageViews to the inner UIScrollViews, one UIImageView to each inner UIScrollView. Set each UIScrollView's content size to each UIImageView's size.

  • Set min and max zoom scales for each inner UIScrollView and set each of the inner UIScrollView's delegate to your View Controller. In the delegate's viewForZoomingInScrollView, return the appropriate UIImageView for the UIScrollView that is passed. (To do this, just keep each of the UIImageViews in an NSArray and set the corresponding UIScrollView's tag property to the index of the appropriate UIImageView. You can then read the tag in the UIScrollView passed to viewForZoomingInScrollView and return the appropriate UIImageView from the NSArray).

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

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

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

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

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

That's it. Works just like the photo app.

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

If you have a lot of photos, to save memory you can just have two inner UIScrollViews and two UIImagesViews. You then dynamically flip between them, moving their position within the outer UIScrollView and changing their images as the user scrolls the outer UIScrollView. It's a bit more complex but the same principle.

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

回答by slf

I did some playing around with the native Photos app, and I think I can say with confidence they are using a single UIScrollView. The giveaway is this: zoom in on an image, and pull to the left or right. You will see the next or previous photo. If you tug hard enough, it will even page to the next photo at 1.0f zoom. Flip back and the previously zoomed photo will be back to 1.0f zoom as well.

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

Obivously I didn't write Photos.app, but I'll take a wild guess at how they did it:

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

  • A single UIScrollView and a single UIScrollViewDelegate
  • Populate the UIScrollView with UIImageView children
  • Listen for scrollViewDidScroll:
  • Do some mathand figure out what page you are currently on
  • Listen for viewForZoomingInScrollView:
  • Return a different view depending on the page index
  • Listen for scrollViewDidEndZooming:withView:atScale:and optionally do some anti-aliasing, etc based on the content
  • 单个 UIScrollView 和单个 UIScrollViewDelegate
  • 使用 UIImageView 子项填充 UIScrollView
  • 聆听 scrollViewDidScroll:
  • 做一些数学计算并找出您当前所在的页面
  • 聆听 viewForZoomingInScrollView:
  • 根据页面索引返回不同的视图
  • scrollViewDidEndZooming:withView:atScale:根据内容收听并可选择做一些抗锯齿等

If you decide to try that out, let me know how it works out for you. I'd love to know how you finally end up getting this to work. Even better, post it to github.

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

回答by beOn

I did some playing around with the native Photos app, and I think I can say with confidence they are using a single UIScrollView. The giveaway is this: zoom in on an image, and pull to the left or right. You will see the next or previous photo. If you tug hard enough, it will even page to the next photo at 1.0f zoom. Flip back and the previously zoomed photo will be back to 1.0f zoom as well.

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

This is wrong. I'm using nested scrollviews, and getting exactly the same effect. If you're using some memory management scheme (which I had to start using... my page number is fairly high ('bout 50 each in 2 scrollViews)), then you can use a mechanism similar to whatever you have triggering your page loads / unloads to trigger a zoom reset for the pages -1 and +1 from the current page.

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

I suspect that apple sets this off as soon as the previous pic has disappeared.

我怀疑苹果在上一张照片消失后立即设置了这一点。

What I don't understand is how to achieve smooth scrolling between pages - there's always a very short hang at the moment of transition. Do not get it. I've gotten pretty deep into fixing it - NSInvocationOperations were my first stop, then I made a reusable views queue for the page views (which retain their image views)... still this durned hang.

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

I only have one NSOperationQueue running, and I've tried fiddling with the max number of concurrent operations. My thought was that the main thread was getting clogged by competing Queues, or maybe even one queue trying to do to much... still, the hang.

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

I even tried creating super low-qual versions of my media, in case that was the problem. With each image weighing in at around 10k (these are jpegs, mind you)... you guessed it. The hang's still there.

我什至尝试创建我的媒体的超低质量版本,以防万一。每张图像的重量约为 10k(这些是 jpeg,请注意)......你猜对了。悬念还在。

I'm pretty much resolved to do what I've done before and use TTPhotoViewController from Three20. I've spent some hours swimming through that code, and it's always a great education. At this point, though, I would really like to know where the heck this hang comes from, if only so I can spend my can't-sleep hours wondering about something less brain boiling.

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

回答by Francois

sure would be nice if apple built an image viewer like the photos app into the SDK for us to use. I'm currently using three20 and it works great. But it is a lot of extra stuff to carry around when all you really want is the photo viewer.

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

回答by chings228

i write a code for that , and can be as reference

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

  1. load current view scrollview and imageview .. and for the screen next to the current view , only imageview

  2. remove all view when current page load to save memory , so good for many photo project

  3. use tag to differentiate different scrollview

  1. 加载当前视图 scrollview 和 imageview .. 并且对于当前视图旁边的屏幕,只有 imageview

  2. 当前页面加载时删除所有视图以节省内存,这对许多照片项目来说非常有用

  3. 使用标签区分不同的滚动视图

first page_xxxxslidexxxzoom

第一页_xxxx 滑动xxx飞涨

the download link click here

下载链接点击这里