UIScrollView – A really simple tutorial

It’s very common to have a large amount of data that we want to display on the iPhone/iPod, but there’s no way that we can fit all at the same time on the screen (even on the iPad), that’s one of the functionalities of the UIScrollView.

The UIScrollView it’s a very versatile class, you can handle zooming, panning, scrolling, etc, and I have no intention of explaining all the properties and delegates (well, if you want to know something about the UIScrollView, fell free to request it in the comments, just let me know =D ), the documentation itself is pretty good, so you should give it a look.

In this post I’ll create a very simple project with three scrollable UIViews just to get familiar with the UIScrollView, and in the next post I intend to do some simple zooming example. So, the next  post will be about the UIScrollView as well.

The basics:

IMO, there’s 2 very important properties in UIScrollView, the contentSize and the contentOffset.

The contentsize is the width and height of your content, it’s a CGSize and a property of UIScrollView, let’s say that you have an image that’s 500×500, it would not fit on the iPhone screen, right? So, set your contentsize to 500,500. If you want to add more scrollable space at the bottom or at the top, you can use the property contentInset.top and contentInset.bottom, so you can add some extra space without changing the contentsize. And why would you need these insets? Well, if you have a UINavigationBar or a UIToolBar, like the photos app, you will use this.

Every UIScrollView has a scroll indicator (it’s visible by default, but if you want, you can hide it with showsHorizontalScrollIndicator and showsVerticalScrollIndicator), to give an indication of how far in the content you are, and you can change where the indicator starts using the scrollIndicatorInsets.top just like the contentInsets.

The contentOffset is the point that is currently visible, this point represents the top left of your screen. The contentOffset discards the contentInsets, so it can happen that the contentInset is negative, that’s not a problem.

The only thing that you need to have a functional UIScrollView is the UIView that you want to display and the contentSize of this UIView, so let’s start coding…

Create a View-based Application and name it SimpleScroll. Again, I always use the Window-based Application for my projects, but let’s pick the View-based just to speed things up.

Go to your SimpleScrollViewController class, in the loadView method and create your UIScrollView, we will create it with the same width and heigh as the view from SimpleScrollViewController

UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
Enable the pagination
scroll.pagingEnabled = YES;

If the value of this property is YES, the scroll view stops on multiples of the view bounds when the user scrolls. The default value is NO.

Create all three UIViews
NSInteger numberOfViews = 3;
for (int i = 0; i < numberOfViews; i++) {
CGFloat xOrigin = i * self.view.frame.size.width;
UIView *awesomeView = [[UIView alloc] initWithFrame:CGRectMake(xOrigin, 0, self.view.frame.size.width, self.view.frame.size.height)];
awesomeView.backgroundColor = [UIColor colorWithRed:0.5/i green:0.5 blue:0.5 alpha:1];
[scroll addSubview:awesomeView];
[awesomeView release];
}

The most important part in this for is to understand the xOrigin. This will place every UIView exactly where the previous UIView has stopped, in other words, each UIView will start at the end of the previous one.

Set the UIScrollView contentSize
scroll.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);

The contentSize is just the sum of the widths of the three UIViews, if the width of each UIView is 320, and we have three UIViews, your contentSize width will be 920.

Add the UIScrollView to the SimpleScrollViewController UIView
[self.view addSubview:scroll];
[scroll release];
And you’re done :)
At the end, you should have something like this :
– (void)loadView {
[super loadView];
self.view.backgroundColor = [UIColor redColor];
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scroll.pagingEnabled = YES;
NSInteger numberOfViews = 3;
for (int i = 0; i < numberOfViews; i++) {
CGFloat xOrigin = i * self.view.frame.size.width;
UIView *awesomeView = [[UIView alloc] initWithFrame:CGRectMake(xOrigin, 0, self.view.frame.size.width, self.view.frame.size.height)];
awesomeView.backgroundColor = [UIColor colorWithRed:0.5/i green:0.5 blue:0.5 alpha:1];
[scroll addSubview:awesomeView];
[awesomeView release];
}
scroll.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);
[self.view addSubview:scroll];
[scroll release];
}
As you can see, I changed the background color of the SimpleScrollViewController UIView to red, just to make sure that you can distinguish the content of the UIScrollView.
That is the tutorial, pretty simple, huh? Now you can show all the data that you want on this small screen ;) Next post I’ll write about how to enable zooming using a UIScrollView.

40 thoughts on “UIScrollView – A really simple tutorial

    1. treviewz

      Great tutorial and it works! But, can you tell me how do you add multiple images in the UIView named awesome?

      For example, displaying an image on each page that is scrolled.

      Thanks!

      Reply
      1. iDevZilla Post author

        You need to add the images in the UIScrollView in the correct position, like I did with the colors in this example, and then add the scrollview to the UIView.

  1. treviewz

    Alright! Thanks alot. This has helped me. Really appreciated! I have finally manage to understand about UIView and UIScrollView.

    Reply
    1. iDevZilla Post author

      Yes, you can create a xib file that it’s a UIView and do the exact same thing as I did in this example, but replace the UIView creation for the IBOutlet that it’s your UIView

      Reply
  2. Joe

    Thanks for the responses. Going back a step. I’ve been able to implement numerous scrolling UIImageView examples (which tile images) but have not been able to find out how to scroll tiled UIViews instead (to allow custom built pages with buttons, positioned alerts ect…).

    My main problem is knowing where best to place my custom IUViews. I’m guessing they would be better off in the nib file that contains the UIScrollView. If so, should they be nested inside the UIScrollView or does that not matter?

    Reply
  3. Joe

    Yeyhey, Just got your scroll app to work. That is the shortest and neatest piece of code I’ve seen that implements scrolling! No to find the illusive bit of code to replace your for loop contents :D

    Reply
  4. Joe

    Hi iDevZilla,

    I created 3 xib files and hooked up the viewcontrollers and can successfully insert a view by adding [awesomeView insertSubview:view1.view atIndex:0]; on the end of your for loop.

    I was expecting my view ‘view1’ to show up three times tiled. But it only appears on the last (3rd) page. Would you know why?

    Would be grateful for any help.

    Reply
  5. Joe

    My last comment to you (“At bloody last” thinks iDevZilla). I was able adapt your script to load up all three UIViews. Below is the final code.

    – (void)loadView {
    [super loadView];
    self.view.backgroundColor = [UIColor redColor];
    UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    scroll.pagingEnabled = YES;
    NSInteger numberOfViews = 3;

    view1.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    [scroll addSubview:view1.view];
    view2.view.frame = CGRectMake(self.view.frame.size.width, 0, self.view.frame.size.width, self.view.frame.size.height);
    [scroll addSubview:view2.view];
    view3.view.frame = CGRectMake(self.view.frame.size.width*2, 0, self.view.frame.size.width, self.view.frame.size.height);
    [scroll addSubview:view3.view];

    scroll.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);
    [self.view addSubview:scroll];
    [scroll release];
    }

    If it wasn’t for you iDevZilla, i wouldn’t have continued trying to get UIViews to work in a UIScrollView.

    Cheers

    Reply
  6. Pingback: iOS Development: eine Sammlung an hilfreichen Tutorials und Webseiten – blog.mixable.de

  7. mark baer

    Good stuff, I was able to get your sample to work. I am still having difficulty getting my sample to work. I have a “form” with many fields, buttons, etc that fits perfectly in “Portrait” mode…When the user rotates to “Landscape” mode, the bottom of the form goes off of the ipad. That is when I would like the scroller to kick in. I’m having difficulties getting the scroller to work in that scenario. Do you have any recommendations? Do I have to change the content size of the scroller when the orientation changes? If so, how do I detect that?

    Any help would be great. This stupid little problem is killing me.

    thanks again…good stuff.

    Reply
  8. Greg The Good Guy

    Nice tutorial. It helped me a lot. But i have to say man, i don’t know if you already know but.. you are colorblind. That color is green and not red.

    Reply
    1. iDevZilla Post author

      Thanks.
      Not sure if I understood your comment.
      There are 4 colors in this app, 3 in the UIScrollView (pink, grey and green) and red on self.view.

      I wrote
      “As you can see, I changed the background color of the SimpleScrollViewController UIView to red, just to make sure that you can distinguish the content of the UIScrollView.”

      The UIView is red, the screenshot is from a transition between view 2 and 3 :)

      Reply
  9. Paul (you guessed it,) Slapikas

    Hi iDevzilla:
    Thanks for your great tutorial on scroll view. I was trying to incorporate scrolling views into an existing app. The app has buttons that are out of sight beneath the existing image view (it doesn’t scroll). I created, what appears to be, custom buttons. It works. I was hoping to just replace the existing image view with a scrolling view. I want the user to be able to “tap through” whatever scrolling image happens to be in view at the time. Naturally, the buttons beneath the scrolling view are always in the same place. It doesn’t work. I can’t “tap through” the scrolling image to get at the buttons that are beneath it. Is there a way to do this?

    Incidentally, in reading your advice to developers on your website about reading the manual/documentation, I find it is very hard to understand Apple’s documentation. Maybe I have a mental block. I find that I can only understand what a “normal” person writes or says. No disrespect to Apple or other technical persons. I have always jokingly referred to non-techies as normal people – and after programming for several decades (mainframe), I have noticed a real difference between IT guys and “normal” people.(It’s a good thing – there’s room for both on this planet.)

    Reply
  10. Coy

    What precisely seriously motivated u to write “UIScrollView – A really simple tutorial |
    iDevzilla” midwestwg ? I actuallyhonestly adored the
    post! Thanks for your effort ,Freeman

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s