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 this tutorial I’ll show you how to create a sliding view that can be used for showing the user a short message. 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://iosdevelopertips.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.

11 Comments

  1. Great tutorial! Keep them coming! Im working on one that will pass in an image as well.

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

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

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

  5. To avoid issue of release msgVC

    // Cleanup...somewhere down the line, you need to do this
    //  [msgVC release];

    I changed hideMsg function to release automatically the view after animation is done:

    - (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 {
        [self release];
    }
  6. 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.

  7. Absolutely fantastic! Saved me HOURS of tinkering. Thanks!

  8. 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];
    }

Comments are closed.