Friday, October 30, 2009

A simple scrolling UILabel for iPhone devs

Here's a simple class which mimics the most common features of a UILabel, yet will act like a horizontally scrolling marquee. It is actually a subclass of UIScrollView, so to use it with Interface Builder, you will need to create a UIScrollView item and then change its class to this class - which I called AutoScrollLabel.

If you don't care about the technical details of how it works and just want to use it, you can download the class files here:

http://stormyprods.com/sampleCode/AutoScrollLabel.zip

To use the class, simply set the text and if the text is wider than the allocated space in the view, it will automatically scroll. Here's a very simple example:


autoScrollLabel.text = @"Hi Mom! How are you? I really ought to write more often.";
autoScrollLabel.textColor = [UIColor yellowColor];


The class also supports the font property, so you can set the font as you normally would for a UILabel.

In addition, there are a few properties related to the scrolling:

scrollDirection: set to AUTO_SCROLL_LEFT (default) or AUTO_SCROLL_RIGHT
scrollSpeed: set to the number of pixels per second (default is 30)
pauseInterval: set to the number of seconds to pause when the end of the text is reached. (default is 0.5)
bufferSpaceBetweenLabels: how much blank space between the end of the text and the beginning of the next instance

It turns out this autoscrolling feature was fairly easy to implement. I'm surprised there isn't already something like this in the SDK. The scrolling is implemented using two UILabels contained in a UIScrollView. Each label contains an identical copy of the text and the labels are resized to be just large enough to hold the text without any truncation.

If the text in the UILabel is wider than the containing UIScrollView, then the two UILabels are laid out side-by-side, and the scroll view is animated to scroll from the beginning of one label to the beginning of the next label. The second label is there just to give the illusion of the text looping forever.

The class registers itself as the delegate for the scrolling animation block, so when the animation block ends, it waits the defined pause time, and then just performs another animated scroll, in which case the scroll view is reset back to the beginning of the first label and the process is repeated.

And that's it! Pretty simple. The animation block feature of a UIView does all the hard work.

I hope others find this useful. If you notice any problems in the code, please let me know.

10 comments:

Keyvisuals said...

Very cool and so easy to implement! I can't wait to use this in a project. Thanks for sharing.

G. Crisp said...

I'm attempting to use this in a project, but it doesn't seem to be working. The class gets instantiated just fine, and the methods are being called, but I see no text.

Can you post some sample code for how to use this class? Thanks!

Mostly Torn said...

The default text color in the class is WHITE, so if you are doing this with a white background , you'll need to change the text color to something else, otherwise you won't see it.

If this is not the problem you are encountering, please let me know and I'll post a sample project demonstrating it's use. Probably won't have time to do it today, though.

Rahul Vyas said...

outstanding work.i will use it in my future apps.thanks for creating this.

Nick Dalton said...

Worked right out of the box. Thank you!

Simon said...

Hi there, for me it's working great, but the text won't change the font color. I already did myLabel.textColor = [UIColor blackColor]; but it isn't working. Also is there a way to do a dropshadow, like you can do with the UILabel?

Nick Dalton said...

I just noticed something "interesting" on 2.x devices: The AutoScrollLabel fails to display anything on screen if the text string is too long.

The limit seems to be somewhere around 2000 pixels width for each UILabel. I'm not sure if the size limitation is in UILabel or UIScrollView. In any case it's a OS 2.x limitation and nothing is wrong with the AutoScrollLabel component.

Leaving this comment here to hopefully save anybody else a few hours of debugging time...

Anonymous said...

Super! Was looking for exactly this! Thanks for this!

necronomicon said...

there's an issue with the pause; using sleepForTimeInterval does freeze the whole application. (That's what happened to me at least). Here's a solution: change
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{

[NSThread sleepForTimeInterval:pauseInterval];
[NSTimer

if ([finished intValue] == 1 && label[0].frame.size.width > self.frame.size.width){
[self scroll];
}
}

with
- (void)}animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
[NSTimer scheduledTimerWithTimeInterval:pauseInterval target:self selector:@selector(scroll) userInfo:nil repeats:NO];
}

Mostly Torn said...

Thanks for the tip Necronomicon.

I've updated the code so it no longer blocks in the foreground thread.


All content copyright © 2009  Brian Stormont, unless otherwise noted.   All rights reserved.