Sliding Views On and Off Screen – Part 1 – Creating a Reusable Sliding Message Widget
Editor’s Note: The second part of this series Sliding Views On and Off Screen – Part 2 – Read Contributions shows two additional ways to work with sliding views, one using Interface Builder, another using a UIView.
In the previous post on the Bikini.com Supermodel party application, I mentioned that I was planning to show how I implemented some of the features of the application.
One aspect that is consistent throughout the application is the sliding of views on and off screen. I was tiring of the out-of-the-box transitions that are included with iPhone SDK and was intrigued with the idea of sliding views into place.
In this tutorial I’ll show you how to create a sliding view that can be used for showing the user a short message. For example, in the Bikini app, once I saved an image to the camera roll to be available as wallpaper, I would show a message to the user that the file was successfully saved. There is no interaction required from the user (that is, no OK, Cancel or other buttons). The code in this tutorial will be similar, the finished application is shown below:
We begin by creating a message viewcontroller:
#import <UIKit/UIKit.h> @interface SlidingMessageViewController : UIViewController { UILabel *titleLabel; UILabel *msgLabel; } - (id)initWithTitle:(NSString *)title message:(NSString *)msg; - (void)showMsgWithDelay:(int)delay; @end
Each message will have a title, which is displayed in bold, and a message. Notice the initWithTitle method, which provides a means to reuse this object for any message we need to show. Also, the showMsgWithDelay method specifies how long to show the message before sliding offscreen.
The implementation of the SlidingMessageViewController is shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | // // SlidingMessageViewController.m // // http://mobiledevelopertips.com // #import "SlidingMessageViewController.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Private interface definitions *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ @interface SlidingMessageViewController(private) - (void)hideMsg; @end @implementation SlidingMessageViewController /************************************************************************** * * Private implementation section * **************************************************************************/ #pragma mark - #pragma mark Private Methods /*------------------------------------------------------------- * *------------------------------------------------------------*/ - (void)hideMsg; { // Slide the view down off screen CGRect frame = self.view.frame; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:.75]; frame.origin.y = 480; self.view.frame = frame; // To autorelease the Msg, define stop selector [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; [UIView commitAnimations]; } - (void)animationDidStop:(NSString*)animationID finished:(BOOL)finished context:(void *)context { // Release [self release]; } /************************************************************************** * * Class implementation section * **************************************************************************/ #pragma mark - #pragma mark Initialization /*------------------------------------------------------------- * *------------------------------------------------------------*/ - (id)initWithTitle:(NSString *)title message:(NSString *)msg { if (self = [super init]) { // Notice the view y coordinate is offscreen (480) // This hides the view self.view = [[[UIView alloc] initWithFrame:CGRectMake(0, 480, 320, 90)] autorelease]; [self.view setBackgroundColor:[UIColor blackColor]]; [self.view setAlpha:.87]; // Title titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, 280, 30)]; titleLabel.font = [UIFont boldSystemFontOfSize:17]; titleLabel.text = title; titleLabel.textAlignment = UITextAlignmentCenter; titleLabel.textColor = [UIColor whiteColor]; titleLabel.backgroundColor = [UIColor clearColor]; [self.view addSubview:titleLabel]; // Message msgLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, 280, 80)]; msgLabel.font = [UIFont systemFontOfSize:15]; msgLabel.text = msg; msgLabel.textAlignment = UITextAlignmentCenter; msgLabel.textColor = [UIColor whiteColor]; msgLabel.backgroundColor = [UIColor clearColor]; [self.view addSubview:msgLabel]; } return self; } #pragma mark - #pragma mark Message Handling /*------------------------------------------------------------- * *------------------------------------------------------------*/ - (void)showMsgWithDelay:(int)delay { // UIView *view = self.view; CGRect frame = self.view.frame; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:.75]; // Slide up based on y axis // A better solution over a hard-coded value would be to // determine the size of the title and msg labels and // set this value accordingly frame.origin.y = 390; self.view.frame = frame; [UIView commitAnimations]; // Hide the view after the requested delay [self performSelector:@selector(hideMsg) withObject:nil afterDelay:delay]; } #pragma mark - #pragma mark Cleanup /*------------------------------------------------------------- * *------------------------------------------------------------*/ - (void)dealloc { if ([self.view superview]) [self.view removeFromSuperview]; [titleLabel release]; [msgLabel release]; [super dealloc]; } @end |
How it Works
Most of this is pretty straightforward, the good stuff begins on line 62 – notice how the y coordinate is set to 480, which sets the view offscreen (off the bottom). If you want to create a view that slides in from the left, you would setup the frame, so the x coordinate would be offscreen. For example, -320 for the x coordinate would offset a view that is 320 pixels wide, so it is not visible.
We slide the view into place inside the method showMsgWithDelay. We setup the animation on lines 99 and 100. On lines 106 and 107 we adjust the frame y coordinate to where we want the view to be shown (all the other frame values stay the same). Line 109 commits the animation, which will providing the sliding effect we are after.
The code on line 112 sets the method to call once the specified delay time is reached.
Calling the code
Using the class created above is as simple as creating a new object, adding as a subview and calling the showMsgWithDelay method:
SlidingMessageViewController *msgVC = [[SlidingMessageViewController alloc] initWithTitle:@"Sliding Message View" message:@"With a 5 second delay"]; [window addSubview:msgVC.view]; // Show the message for 5 seconds [msgVC showMsgWithDelay:5];
Sliding entire Screen
You can follow the same idea for any view that you would like to slide into place. For example, if you have a view that encompasses the whole screen, say 320×460, and you would like to slide the view in from the left, set the original frame so the x coordinate keeps the entire view offscreen:
// -320 sets the view offscreen to the left self.view = [[[UIView alloc] initWithFrame:CGRectMake(-320, 0, 320, 460)] autorelease];
You then setup the animation sequence as I did above, and set the x coordinate to 0, and commit the animation. To slide the view offscreen agin, set the x coordinate back to -320 and commit another animation sequence.
I used this same idea throughout the Bikini application, creating views with offscreen coordinates, and using short animation sequences to slide each view onscreen by updating the frame so it’s visible. It’s a nice effect.
Enhancement and Additional Ideas
This is a bare bones widget, there are any number of additional ideas that you might consider adding. For example, you could add one or more optional buttons to be displayed. In this case you could create a modal message by skipping the delay timer and have Ok/Cancel buttons.
Another option would be to allow the message to slide down from the top, or in from the left or right. With a little work, you could create a very flexible sliding widget.
If you modify the original example with some nice features, let me know and I can post the updated code here (giving appropriate credit/links for the updates).
Download Xcode Project
You can download the entire Xcode project: Sliding Views Xcode Project.
Related posts:
- Creating Info Button and Increasing Touch Area
- Adding Text Message to an ActionSheet
- Creating a Tabbar



Excellent tutorial, I was looking for something just like this!
[Reply]
Great tutorial! Keep them coming! Im working on one that will pass in an image as well.
[Reply]
Great Tutorial…
One question how could you implement upon touch the pop-up screen goes to the 480 or y view??? I have an intro movie on my app and if someone bypasses the movie they have to wait for the pop-up to go away before they can get to the meat of my app.
Thanks in advance
[Reply]
Hi,
Thx a lot for this ! Tried your Xcode project and works fine in 3.0… in 2.2.1, the scroll off the screen doesn’t work… the view just disappear… weird…
[Reply]
JFMartin,
With 2.2.1, did you try a device or the simulator? I deployed that code in a 2.2.1 build and it seemed to work…
[Reply]
To avoid issue of release msgVC
I changed hideMsg function to release automatically the view after animation is done:
[Reply]
nebula_1979, thanks for the great tip, I’ve updated the original post.
John
[Reply]
Thanks :) I was looking for something Just like this!
[Reply]
Is there a way to make it fire only once? Right now I can keep tapping and creating many copies of this pop up slider.
[Reply]
Absolutely fantastic! Saved me HOURS of tinkering. Thanks!
[Reply]
to avoid problems with releasing i have added to my version a removeFromSuperview check before releasing self.
- (void)animationDidStop:(NSString*)animationID finished:(BOOL)finished context:(void *)context
{
// Release
if ([self.view superview])
[self.view removeFromSuperview];
[self release];
}
[Reply]