首页 > 代码库 > 跑马灯

跑马灯

项目中用到这种效果,索性写了一个通用的组件,可以支持从左到右、从右到左、从上到下、从下到上 4个方向的滚动。

有不完善的地方请指正,谢谢

//
//  ScrollingTextView.h
//  ScrollingText
//
//  Created by Hunk on 14/12/1.
//  Copyright (c) 2014年 Hunk. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, ScrollDirection)
{
    ScrollDirectionFromRightToLeft  = 0,
    ScrollDirectionFromLeftToRight,
    ScrollDirectionFromTopToBottom,
    ScrollDirectionFromBottomToTop
};

@interface ScrollingTextView : UIView
{}

/**
 *  Text array
 *
 *  Default is DefaultScrollingText-1 and DefaultScrollingText-2.
 */
@property (nonatomic, strong) NSArray           *scrollingTextArray;

/**
 *  Scroll direction
 *
 *  Default is ScrollDirectionFromRightToLeft.
 */
@property (nonatomic, assign) ScrollDirection    scrollDirection;

/**
 *  Scroll duration
 *
 *  Default is 2.0 seconds.
 */
@property (nonatomic, assign) NSTimeInterval     duration;

/**
 *  Animating flag
 *  
 *  Default is NO.
 */
@property (nonatomic, assign) BOOL               isAnimating;

/**
 *  Start animating
 *
 *  Before calling this function, set scrollingTextArray, scrollDirection and duration first.
 */
- (void)startAnimating;

/**
 *  Stop animating
 *
 *  @return Stop animating successfully or not.
 */
- (BOOL)stopAnimating;

@end

//
//  ScrollingTextView.m
//  ScrollingText
//
//  Created by Hunk on 14/12/1.
//  Copyright (c) 2014年 Hunk. All rights reserved.
//

#import "ScrollingTextView.h"

@interface ScrollingTextView ()
{
    // Text label
    UILabel     *_textLabel[2];
    
    // Text index
    NSInteger    _index;
    
    BOOL         _animatingEnable;
}
@end

@implementation ScrollingTextView
@synthesize scrollingTextArray  = _scrollingTextArray;
@synthesize scrollDirection     = _scrollDirection;
@synthesize duration            = _duration;
@synthesize isAnimating         = _isAnimating;

- (instancetype)initWithFrame:(CGRect)frame
{
    if(self = [super initWithFrame:frame])
    {
        [self setBackgroundColor:[UIColor clearColor]];
        [self setClipsToBounds:YES];
        [self setOpaque:YES];
        
        // Text label
        _textLabel[0] = [self textLabelWithFrame:self.bounds];
        [self addSubview:_textLabel[0]];
        
        _textLabel[1] = [self textLabelWithFrame:CGRectMake(CGRectGetWidth(self.bounds), 0.0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
        [self addSubview:_textLabel[1]];
        
        // Initialize data
        self.scrollingTextArray = @[@"DefaultScrollingText-1", @"DefaultScrollingText-2"];
        self.scrollDirection    = ScrollDirectionFromLeftToRight;
        self.duration           = 2.0;
        self.isAnimating        = NO;
        _index                  = 0;
        _animatingEnable        = YES;
    }
    return self;
}

#pragma mark -
#pragma mark Set scroll text array
-(void)setScrollingTextArray:(NSArray *)scrollingTextArray
{
    if(_scrollingTextArray != scrollingTextArray)
    {
        _scrollingTextArray = scrollingTextArray;
    }
    
    if([_scrollingTextArray count] >= 2)
    {
        [_textLabel[0] setText:[_scrollingTextArray objectAtIndex:0]];
        [_textLabel[1] setText:[_scrollingTextArray objectAtIndex:1]];
        _index = 1;
    }
}

#pragma mark -
#pragma mark Set scroll direction
- (void)setScrollDirection:(ScrollDirection)scrollDirection
{
    _scrollDirection = scrollDirection;
    
    switch(self.scrollDirection)
    {
        case ScrollDirectionFromRightToLeft:
        {
            [_textLabel[0] setFrame:self.bounds];
            [_textLabel[1] setFrame:CGRectMake(CGRectGetWidth(self.bounds), 0.0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
        }
            break;
        case ScrollDirectionFromLeftToRight:
        {
            [_textLabel[0] setFrame:self.bounds];
            [_textLabel[1] setFrame:CGRectMake(-CGRectGetWidth(self.bounds), 0.0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
        }
            break;
        case ScrollDirectionFromTopToBottom:
        {
            [_textLabel[0] setFrame:self.bounds];
            [_textLabel[1] setFrame:CGRectMake(0.0, -CGRectGetHeight(self.bounds), CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
        }
            break;
        case ScrollDirectionFromBottomToTop:
        {
            [_textLabel[0] setFrame:self.bounds];
            [_textLabel[1] setFrame:CGRectMake(0.0, CGRectGetHeight(self.bounds), CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
        }
            break;
        default:
            break;
    }
}

#pragma mark -
#pragma mark Start animating
- (void)startAnimating
{
    _animatingEnable = YES;
    [self setIsAnimating:YES];
    
    [UIView animateWithDuration:self.duration
                          delay:0.0
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         switch(self.scrollDirection)
                         {
                             case ScrollDirectionFromRightToLeft:
                             {
                                 [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, -CGRectGetWidth(self.bounds), 0.0)];
                                 [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, -CGRectGetWidth(self.bounds), 0.0)];
                             }
                                 break;
                             case ScrollDirectionFromLeftToRight:
                             {
                                 [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, CGRectGetWidth(self.bounds), 0.0)];
                                 [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, CGRectGetWidth(self.bounds), 0.0)];
                             }
                                 break;
                             case ScrollDirectionFromTopToBottom:
                             {
                                 [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, 0.0, CGRectGetHeight(self.bounds))];
                                 [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, 0.0, CGRectGetHeight(self.bounds))];
                             }
                                 break;
                             case ScrollDirectionFromBottomToTop:
                             {
                                 [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, 0.0, -CGRectGetHeight(self.bounds))];
                                 [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, 0.0, -CGRectGetHeight(self.bounds))];
                             }
                                 break;
                             default:
                                 break;
                         }
                     }
                     completion:^(BOOL finished) {
                         [self setIsAnimating:NO];
                         if(YES == _animatingEnable)
                         {
                             [self animationDidStoped];
                         }
                     }];
}

- (BOOL)stopAnimating
{
    if(self.isAnimating)
    {
        _animatingEnable = NO;
        
        return YES;
    }
    return NO;
}

#pragma makr -
#pragma makr Private method
// Animation stoped
- (void)animationDidStoped
{
    _index++;
    if(_index >= [_scrollingTextArray count])
    {
        _index = 0;
    }
    
    if([_scrollingTextArray count] > _index)
    {
        switch(self.scrollDirection)
        {
            case ScrollDirectionFromRightToLeft:
            {
                if(_textLabel[0].frame.origin.x < 0)
                {
                    [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, 2 * CGRectGetWidth(self.bounds), 0.0)];
                    [_textLabel[0] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
                else
                {
                    [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, 2 * CGRectGetWidth(self.bounds), 0.0)];
                    [_textLabel[1] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
            }
                break;
            case ScrollDirectionFromLeftToRight:
            {
                if(_textLabel[0].frame.origin.x >= CGRectGetWidth(self.bounds))
                {
                    [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, -2 * CGRectGetWidth(self.bounds), 0.0)];
                    [_textLabel[0] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
                else
                {
                    [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, -2 * CGRectGetWidth(self.bounds), 0.0)];
                    [_textLabel[1] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
            }
                break;
            case ScrollDirectionFromTopToBottom:
            {
                if(_textLabel[0].frame.origin.y >= CGRectGetHeight(self.bounds))
                {
                    [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, 0.0, -2 * CGRectGetHeight(self.bounds))];
                    [_textLabel[0] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
                else
                {
                    [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, 0.0, -2 * CGRectGetHeight(self.bounds))];
                    [_textLabel[1] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
            }
                break;
            case ScrollDirectionFromBottomToTop:
            {
                if(_textLabel[0].frame.origin.y <= -CGRectGetHeight(self.bounds))
                {
                    [_textLabel[0] setFrame:CGRectOffset(_textLabel[0].frame, 0.0, 2 * CGRectGetHeight(self.bounds))];
                    [_textLabel[0] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
                else
                {
                    [_textLabel[1] setFrame:CGRectOffset(_textLabel[1].frame, 0.0, 2 * CGRectGetHeight(self.bounds))];
                    [_textLabel[1] setText:[_scrollingTextArray objectAtIndex:_index]];
                }
            }
                break;
            default:
                break;
        }
        
        [self startAnimating];
    }
}

// Init text label
- (UILabel *)textLabelWithFrame:(CGRect)frame
{
    UILabel *textLabel = [[UILabel alloc] initWithFrame:frame];
    [textLabel setBackgroundColor:[UIColor clearColor]];
    [textLabel setFont:[UIFont systemFontOfSize:12]];
    [textLabel setLineBreakMode:UILineBreakModeTailTruncation];
    return textLabel;
}

@end


跑马灯