2

I wish to loop a UIScrollView, but not in the manner of most that loop through a list of views, just one that scrolls through one subview, but loops around seamlessly.

Essentially, I'm trying to make a map view, that I can zoom in and out of and keeps scrolling around and around.

anyone got any tips?

Khrob
  • 1,229
  • 2
  • 12
  • 12

1 Answers1

4

I was playing around with the same sort of problem a while ago and hacked together a quick demo of one solution. Off hand I'm not sure if a map view, which might be built of many tiles, would be easier or harder to manage.

https://github.com/jonah-carbonfive/WrappingScrollView

Here's what I'm doing in case it isn't clear from the code.

  1. Create a single view containing whatever content you want to display. We'll call this the "tile view".
  2. Display your tile view centered in a UIScrollView's content view. Make the content view significantly larger than the tile view (see below for how much larger).
  3. Create an image of the contents of your tile view.
  4. Create UIImageView "tiles" containing this image and position them around the tile view to fill your scroll view's content view. That might be a lot of UIImageViews but they share a single image so the memory footprint isn't too bad.
  5. Now you have a large scroll view which appears to wrap it's contents at least once but you'll still hit the edge if you scroll far enough.
  6. In the scroll view's -scrollViewDidScroll: delegate method check if your tile view has scrolled completely out of sight, if so reposition the scroll view's content offset to reposition the content view so the tile view is back in the middle of the visible region. Done correctly the user never notices that you jumped from looking at an image of the tile view back to the tile view itself.
  7. But wait! Only the central tile view will actually respond to touches. All the other copies of it are just images after all. We can work around this by overriding -hitTest:withEvent: to reposition the tile view to take the place of whatever image view the user attempts to touch before calling super. Now all touches reach the tile view.
  8. Make sure to update the image of the tile view any time the tile view is redrawn.

That's kind of crazy but it let me throw arbitrary interactive UIViews and UIControls into a container and let them wrap off one side and back onto the other.


Honestly this is probably not a great solution for you. If I knew that I wanted to draw a map which could wrap in one or more dimensions I would break the map into many tiles. Detect touches on some container view much like UIScrollView does, and reposition the tiles as the user moves their touches. Removing tiles as they scroll out of sight and reusing them to show newly visible regions of the map. In a simple case you might be able to implement this using just two copies of a map image. In a complex case you're recreating much of UIScrollView; scaling the tiles you display and possibly loading different tile sets at different resolutions to reduce memory use and increase resolution while zooming.

Jonah
  • 17,918
  • 1
  • 43
  • 70
  • This question is probably a better example of how to handle the sort of functionality Khrob described: http://stackoverflow.com/questions/3071623/make-uiscrollview-wrap-around – Jonah Jan 13 '11 at 03:23
  • Thanks Jonah, for the answer and the link. Playing around with it, I didn't realise you could abut different pages in a UIScrollView without the separation. This combined with your technique seems to do the trick. I'll post a sample app as soon as I get a chance. – Khrob Feb 03 '11 at 22:18
  • OK, got pretty much the behaviour I'm after. Instead of putting multiple subviews in with the same image, I just doubled up the one image. – Khrob Feb 08 '11 at 11:49
  • Now all I need to do is check during -scrollViewDidScroll if contentOffset.x < contentSize.width * 0.25 or > contentSize.width * 0.75 then add or subtract half the width accordingly. [link](https://docs.google.com/leaf?id=0B7--XCpu3Or_MDAyNzU0MjktMjAxZS00NjQ1LTk3YzAtNGYzOGQwNTc4NjAy&hl=en) (Sample Project) – Khrob Feb 08 '11 at 11:57