UIScrollView image/photo viewer with paging enabled and zooming


UIScrollView image/photo viewer with paging enabled and zooming



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

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

I found the following project on github:

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

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 UIScrollView subclass 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.

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 contentsize etc. Then when you zoom back to 1.0f it adds the other views back and puts things all back in order.

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/offset etc. 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.

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

UIScrollView: After zooming, content inset is ignored and content is left in the wrong position.

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.

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.

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

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.


How to do smooth scrolling in UIScrollView?

1:

iPhone: Sending large data with Game Kit
UPDATE. How to solve this memory leak (iPhone)? I deleted my previous answer for the reason this of the news below.... How do I call an array value and use it to play a sound file? Big news for those who haven't heard. Property attribute “retain” doesn't seem to be working?Apple has released the 2010 WWDC session videos to all members of the iphone developer program. How to set up single array or dictionary for use in multiple datasources?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.. Memory management and performSelectorInBackground: It does not use private api either. tableView footer strange behaviorHere is a link to the sample code download. You will probably need to login to gain access.. Check This. And, here is a link to the iTunes WWDC page:. Check This.

2:

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 must 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 must be zoomed and panned, and optional (customisable) captions must be displayed. The browser must also be used to allow the user to select one or more photos using either the grid or main image view.. MWPhotoBrowser Screenshots.

3:

You say you've seen discussions of nesting UIScrollViews although don't want to go there - although this is the way to go! It works easily and well.. It's essentially what Apple does in its PhotoScroller case (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 another 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:.
  • 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 this is passed. (To did 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 must then read the tag in the UIScrollView passed to viewForZoomingInScrollView and return the appropriate UIImageView from the NSArray)..
That's it. Works just like the photo app. . If you have a lot of photos, to save memory you must 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 although the same principle..

4:

I did any playing around with the native Photos app, and I think I must 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.. Obivously I didn't write Photos.app, although I'll take a wild guess at how they did it:.
  • A single UIScrollView and a single UIScrollViewDelegate
  • Populate the UIScrollView with UIImageView children
  • Listen for scrollViewDidScroll:
  • Do any math and 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 did any anti-aliasing, etc based on the content
If you decide to try this out, let me know how it works out for you. I'd love to know how you finally end up receive ting this to work. Even better, post it to github..

5:

I did any playing around with the native Photos app, and I think I must 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..
This is wrong. I'm using nested scrollviews, and receive ting exactly the same effect. If you're using any memory management scheme (which I had to start using... my page number is fairly high ('bout 50 each in 2 scrollViews)), then you must 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.. I suspect this 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 receive 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.. I only have one NSOperationQueue running, and I've tried fiddling with the max number of concurrent operations. My thought was this the main thread was receive ting clogged by competing Queues, or maybe even one queue endeavor to did to much... still, the hang.. I even tried creating super low-qual versions of my media, in case this was the problem. With each image weighing in at around 10k (these are jpegs, mind you)... you guessed it. The hang's still there.. I'm pretty enough resolved to did what I've done before and use TTPhotoViewController from Three20. I've spent any hours swimming through this 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 must spend my can't-sleep hours wondering around any thing less brain boiling..

6:

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. .

7:

i write a code for this , and must 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 .
first page_xxxxslidexxxzoom. the download link click here .

8:

Take a look at https://github.com/facebook/three20/blob/master/src/Three20UI/Headers/TTPhotoViewController.h Not sure if that's what you are looking for.


76 out of 100 based on 51 user ratings 286 reviews