Search code examples
objective-cios7uiscrollviewnstimer

How to Scroll the text in label automatically


I have an array , data of which 'm displaying on scrollview using UILabel. I can scroll right and left. But I want to add one more feature in that which is automatic scrolling of the label text on scrollview. That means even if I do not scroll I want it to move by itself. My code for scrolling is as below:

- (void)viewDidLoad
{
    [super viewDidLoad];

    _scrollView.contentInset=UIEdgeInsetsMake(0, 300, 0, 300);

    NSMutableArray *items=[[NSMutableArray alloc] initWithObjects:@"A walk to remember",@"The Last song",@"The Notebook",@"Dear John",@"The Longest Ride",nil];

    CGFloat y = 10;
    self.label = [[UILabel alloc]initWithFrame:CGRectMake(0,y,800, 25)];

    for(int i=0;i<[items count];i++){
          y+=20;        
         NSString* lab=[items objectAtIndex:i];
        _label.backgroundColor=[UIColor clearColor];
        lab=[items componentsJoinedByString:@" | "];
        NSLog(@"label:%@",lab);
        [self.label setLineBreakMode:NSLineBreakByWordWrapping];
        [self.label setText:lab];     
    }   

    NSTimer *timer = [NSTimer timerWithTimeInterval:1
                                             target:self
                                           selector:@selector(timer)
                                           userInfo:nil
                                            repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 

    //[_scrollView scrollRectToVisible:NSMakeRange(0,0,0.0) animated:YES]; 
    [_scrollView addSubview:_label];
    [UIView commitAnimations];    

    _scrollView.contentSize=CGSizeMake(_scrollView.frame.size.width*[items count], _scrollView.frame.size.height);   
    }

timer code:

-(void)timer {

[self.label setText:[NSString stringWithFormat:@" %@", self.label.text]];

}

Please help me how could I make the label text move horizontally. Thanks for any help


Solution

  • That's a fairly horrible way to implement scrolling if I may so so! You're scrolling by inserting incremental spaces to the left of the string. There is a much easier way to do this!

    • Keep your code that adds the UILabels to your scroll view
    • Get rid of the NSTimer stuff
    • Add a basic UIView animation to animate the scrollview's content offset.

    Something like this:

    [UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            _scrollview.contentOffset = CGPointMake(-50.0f, 0.0f);
        } completion:nil];
    

    This will slide the whole scrollview left by 50 points over 0.3secs. You can play around with the settings.

    btw, typically you'd create the UILabels in viewDidLoad (as you have it) but put the animation in viewWillAppear or viewDidAppear

    Have had another look at your code. I thought you were adding multiple UILabels to your uiscrollview but actually you're adding just one with a long text string.

    You can simplify your code to set up the label quite a bit, then implement the scrolling animation per the below.

    NSMutableArray *items=[[NSMutableArray alloc] initWithObjects:@"A walk to remember",@"The Last song",@"The Notebook",@"Dear John",@"The Longest Ride",nil];
    
    CGFloat y = 10;
    self.label = [[UILabel alloc]initWithFrame:CGRectMake(0,y,800, 25)];
    [self.label setLineBreakMode:NSLineBreakByWordWrapping];
    [self.label setBackgroundColor: [UIColor clearColor]];
    [self.label setText: [items componentsJoinedByString:@" | "]];
    

    EDIT

    To your question about how to show the whole line scrolling and then repeating, there are a couple of steps here.

    • Make the UILabel wide enough to take all the text on a single line - i.e. increase the width so that it's big enough to fit all the text. You can do this by trial and error or use (CGSize)sizeThatFits:(CGSize)size

    to get the size. You call CGSize size = self.label sizeThatFits:CGSizeMake(CGFloatMax, self.label.frame.size.height) to get the size then apply this to the label's frame:

    CGRect frame = self.label.frame;
    frame.size.width = size.width; //calculated above with sizeThatFits
    self.label.frame = frame; //update the frame
    
    • Now scroll the scrollview by the full width. So the animateWithDuration code would become:

      _scrollview.contentOffset = CGPointMake(-size.width, 0.0f);

    • The final step is how to make it restart once it's got to the end. Not sure what effect you want here? Should it jump back to the start? (if so set the contentOffset x to zero), or continue scrolling? (if so, use a trick like adding a second UILabel at the end of the first.

    BTW, if what you're after is a simple scrolling text like a banner on a webpage, then I suggest you don't bother with the scrollview at all. Instead add the UILabel to self.view and then animate the UILabel's frame origin directly.