iPhone Programming: Using the Scroll View

One of the most common questions I hear often during an iPhone development course is how do you populate your View window with more views than what you can see on the View window? The obvious answer is to use a UIScrollView and then add all other views into it. However, the concept sounds simple, but in reality it requires a little more work than you would expect. Hence in this article I will walk you through the use of the UIScollView. At the same time, I will also cover another very common problem faced by developers — how to shift your views upward when a keyboard pops up to enable you to enter some text. [login]

Using the UIScrollView

To see the UIScrollView in action, launch Xcode and create a new View-based Application (iPhone) project and name it as Scroller. Double-click on the ScrollerViewController.xib file located in the Resources folder to edit it in Interface Builder. Populate the View window with a UIScrollView (see Figure 1). Figure 1. Populating the View window with a UIScrollViewAdd two Round Rect Button views to the UIScrollView (see Figure 2). Figure 2. Adding two Round Rect Button views to the UIScrollViewNow, you can add some more views to the UIScrollView so that the user can view more than what the View window can display at a time. To do so, perform the following steps:
    * Click on the UIScrollView to select it. If you cannot select it, click on the title bar of the View window first and then click on the UIScrollView again.

    * Shift the UIScrollView upwards (see left of Figure 3).

    * Expand the height of the UIScrollView by dragging the center-dot of the UIScrollView downwards. The UIScrollView should now look like Figure 3 (right).

Figure 3. Expanding the size of the UIScrollViewNow, add a Text Field view onto the bottom of the UIScrollView (see Figure 4). Figure 4. Adding a Text Field view to the UIScrollViewSelect the UIScrollView and view its Size Inspector window (see Figure 5). Observe that its size is 320×713 pixels. You will need to use this value in your code, which you will do next. Figure 5. Viewing the size of the UIScrollViewBack in Xcode, add the following code in bold to the ScrollViewController.h file:

#import @interface ScrollerViewController : UIViewController {    IBOutlet UIScrollView *scrollView;}@property (nonatomic, retain) UIScrollView *scrollView;@end

In Interface Builder, control-click and drag the File's Owner item over the UIScrollView. Select scrollView. Next, insert the following code in the ScrollerViewController.m file:

#import "ScrollerViewController.h"@implementation [email protected] scrollView;- (void)viewDidLoad {    //---set the viewable frame of the scroll view---    scrollView.frame = CGRectMake(0, 0, 320, 460);    //---set the content size of the scroll view---    [scrollView setContentSize:CGSizeMake(320, 713)];        [super viewDidLoad];}- (void)dealloc {    [scrollView release];    [super dealloc];}

To test the application on the iPhone Simulator, press Command-R. You can now flick the UIScolllView up and down to reveal all the views contained in it (see Figure 6)! Figure 6. Scrolling the UIScrollView reveals more viewsTap on the Text Field view located at the bottom. The keyboard will automatically appear. However, observe that the Text Field view is now covered by the keyboard (see Figure 7). It is your duty to ensure that the current view is not hidden by the keyboard; the next section will show you how. Figure 7. The Keyboard covering the Text Field view

Scrolling Views Programmatically

On the iPhone, whenever the user taps on a view that accepts keyboard inputs (such as the Text Field and Text View views), the keyboard automatically appears from the bottom of the screen. While it is not your responsibility to display the keyboard, it is your duty to ensure that the current view receiving the input is not blocked by the keyboard. One common way to solve this problem is to use the UIScrollView to contain all your views. When the keyboard appears, you can then programmatically scrolls the UIScrollView upwards. Let's see how to do this.Back in Interface Builder, add a few more Label and Text Field views to the bottom of the UIScrollView (see Figure 8). Figure 8. Adding more views to the UIScrollViewIn the ScrollerViewController.h file, add the following code in bold:

#import @interface ScrollerViewController : UIViewController {    IBOutlet UIScrollView *scrollView;    UITextField *currentTextField;    BOOL keyboardIsShown;}@property (nonatomic, retain) UIScrollView *scrollView;@end

In Interface Builder, right-click on each Text Field view and connect the delegate outlet to the File's Owner item. This step is important as it will ensure that when any of the Text Field view is tapped, three events can be handled:

    " textFieldDidBeginEditing:
    " textFieldDidEndEditing:
    " textFieldShouldReturn:

Let's modify the ScrollerViewController.m file in parts so that you can see the various concepts in work. First, change the content size of the UIScrollView to match its new size. You can confirm this by looking at its Size Inspector window. For my case, the new height is 1040:

- (void)viewDidLoad {    scrollView.frame = CGRectMake(0, 0, 320, 460);    [scrollView setContentSize:CGSizeMake(320, 1040)];            [super viewDidLoad];}

Next, when the View window appears, you will register two notifications - UIKeyboardDidShowNotification and UIKeyboardDidHideNotification. These two notifications allow you to know when the keyboard has appeared and when it has disappeared. You register the notifications via the viewWillAppear: event:

-(void) viewWillAppear:(BOOL)animated {        //---registers the notifications for keyboard---    [[NSNotificationCenter defaultCenter] addObserver:self                                              selector:@selector(keyboardDidShow:)                                                  name:UIKeyboardDidShowNotification                                                object:self.view.window];         [[NSNotificationCenter defaultCenter] addObserver:self                                             selector:@selector(keyboardDidHide:)                                                 name:UIKeyboardDidHideNotification                                                object:nil];}

When any of the Text Field views is tapped, the textFieldDidBeginEditing: event will fire:

//---when a TextField view begins editing----(void) textFieldDidBeginEditing:(UITextField *)textFieldView {      currentTextField = textFieldView;}  

Here, you save a copy of the Text Field currently being tapped. When the user taps on the "return" key on the keyboard, the textFieldShouldReturn: event will be fired:

-(BOOL) textFieldShouldReturn:(UITextField *) textFieldView {      [textFieldView resignFirstResponder];    return NO;}

Here, you hide the keyboard by calling the resignFirstResponder method of the Text Field view, which will then trigger another event - textFieldDidEndEditing:. Here, you set the currentTextField to nil:

//---when a TextField view is done editing----(void) textFieldDidEndEditing:(UITextField *) textFieldView {      currentTextField = nil;}

When the keyboard appears, it will call the keyboardDidShow: method (which is set via the notification):

//---when the keyboard appears----(void) keyboardDidShow:(NSNotification *) notification {    if (keyboardIsShown) return;        NSDictionary* info = [notification userInfo];        //---obtain the size of the keyboard---    NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];    CGSize keyboardSize = [aValue CGRectValue].size;         //---resize the scroll view (with keyboard)---    CGRect viewFrame = [scrollView frame];    viewFrame.size.height -= keyboardSize.height;    scrollView.frame = viewFrame;        //---scroll to the current text field---    CGRect textFieldRect = [currentTextField frame];    [scrollView scrollRectToVisible:textFieldRect animated:YES];        keyboardIsShown = YES;}

Here, you will obtain the size of the keyboard, in particular its height. This is important as the keyboard has different heights depending on whether it is in landscape or portrait mode. You then resize the view frame of the UIScrollView and scroll the Text Field so that it is visible. What happen when the keyboard is visible and the user taps on another Text Field? In this case, the keyboardDidShow: method will be called again, but since the keyboardIsShown is set to YES, the method will immediately exit. If the Text Field view that is tapped is partially hidden, it will automatically be scrolled to a visible region on the View window. When the keyboard disappears, the keyboardDidHide: method will be called:

//---when the keyboard disappears----(void) keyboardDidHide:(NSNotification *) notification {    NSDictionary* info = [notification userInfo];        //---obtain the size of the keyboard---    NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];    CGSize keyboardSize = [aValue CGRectValue].size;        //---resize the scroll view back to the original size (without keyboard)---    CGRect viewFrame = [scrollView frame];    viewFrame.size.height += keyboardSize.height;    scrollView.frame = viewFrame;        keyboardIsShown = NO;}

Here, you restore the size of the view frame of the UIScrollView to the one without the keyboard. Finally, when the View window disappears, remove the notifications that you have set earlier:

-(void) viewWillDisappear:(BOOL)animated {    //---removes the notifications for keyboard---    [[NSNotificationCenter defaultCenter]         removeObserver:self                   name:UIKeyboardWillShowNotification                 object:nil];    [[NSNotificationCenter defaultCenter]         removeObserver:self                   name:UIKeyboardWillHideNotification                 object:nil];}

To test the application, press Command-R. Tap on the various Text Field views and observe the various views scrolling (see Figure 9). Figure 9. The Views scrolling upwards when the keyboard appears

Summary

In this article, you have seen how to use the UIScrollView to contain all your views. Knowing how to use it will make your application much more usable and improve the effective of your application.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: