iOS走马灯上下滚动显示文本

在网上找到的大部分都是横向的走马灯效果,就自己动手谢了一个上下滚动的。说的准确一点的话可能不算走马灯,文本是有停留的,每次显示一条。不停留连续的走马灯效果正在研究,后期补上。
TableViewCell调用

        NSArray * arr = @[@"qwer",@"12345",@"asdfg",@"54321",@"zxcvb",@"09877",@"567889"];

        dynamicMessageTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:shoppersCell];
        if (cell == nil) {
            cell = [[dynamicMessageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:shoppersCell dataArray:arr];
        }
        return cell;

Cell

#import "BTableViewCell.h"

@interface dynamicMessageTableViewCell : BTableViewCell

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier dataArray:(NSArray *)titleArray;
//-(void)info:(NSArray *)titleArray;

@end

BBCyclingLabel

#import "dynamicMessageTableViewCell.h"
#import "BBCyclingLabel.h"

@interface dynamicMessageTableViewCell()
{
    BBCyclingLabel * _bbCyclingLable;
    NSArray * _titleArr;
    UITextField * _text;
    int a;
    int _msgCount;

}

@end

@implementation dynamicMessageTableViewCell
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier dataArray:(NSArray *)titleArray
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

        _text = [[UITextField alloc] initWithFrame:CGRectMake(80, 0, SCREEN_WIDTH-80, 30)];
        _titleArr = [[NSArray alloc] init];
        _titleArr = titleArray;

        UIImageView *imagev = [[UIImageView alloc]initWithFrame:CGRectMake(20, 10, 50, 50)];
        [imagev setImage:GetImage(@"icon_notice.png")];
        [self addSubview:imagev];
        [self createUI];
    }
    return self;
}

-(void)createUI
{
    _bbCyclingLable  = [[BBCyclingLabel alloc]initWithFrame:CGRectMake(80, 0, SCREEN_WIDTH-80, 30) andTransitionType:BBCyclingLabelTransitionEffectScrollUp];

//    [_text addSubview:_bbCyclingLable];
//    _text.borderStyle = UITextBorderStyleRoundedRect;
//    [self addSubview:_text];
    [self addSubview:_bbCyclingLable];

    NSTimer *time = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(change) userInfo:nil repeats:YES];
    [time fire];
    a = 0;
}

-(void)info:(NSArray *)titleArray
{
    _titleArr = titleArray;
}


//数组中的内容仅供测试用,具体内容可以通过后台服务器获取或者写死(数据条数可以改变,我写的是3条)
-(void)change
{
    a++;
    if (0<=a && a<_titleArr.count) {
        _bbCyclingLable.text = [_titleArr objectAtIndex:a];
    }else{
        a=0;
        _bbCyclingLable.text = [_titleArr objectAtIndex:a];
    }
}
//
// Copyright 2012 BiasedBit
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//
//  Created by Bruno de Carvalho -- @biasedbit / http://biasedbit.com
//  Copyright (c) 2012 BiasedBit. All rights reserved.
//

#pragma mark - Enums

typedef enum
{
    // User must provide pre-transition and transition blocks
    BBCyclingLabelTransitionEffectCustom = 0,

    BBCyclingLabelTransitionEffectFadeIn    = 1 << 0,
    BBCyclingLabelTransitionEffectFadeOut   = 1 << 1,
    BBCyclingLabelTransitionEffectCrossFade = BBCyclingLabelTransitionEffectFadeIn |
                                              BBCyclingLabelTransitionEffectFadeOut,

    BBCyclingLabelTransitionEffectZoomIn  = 1 << 2,
    BBCyclingLabelTransitionEffectZoomOut = 1 << 3,

    BBCyclingLabelTransitionEffectScaleFadeOut = BBCyclingLabelTransitionEffectFadeIn |
                                                 BBCyclingLabelTransitionEffectFadeOut |
                                                 BBCyclingLabelTransitionEffectZoomOut,
    BBCyclingLabelTransitionEffectScaleFadeIn  = BBCyclingLabelTransitionEffectFadeIn |
                                                 BBCyclingLabelTransitionEffectFadeOut |
                                                 BBCyclingLabelTransitionEffectZoomIn,

    // These two move the entering label from above/below to center and exiting label up/down without cross-fade
    // It's a good idea to set the clipsToBounds property of the BBCyclingLabel to true and use this in a confined space
    BBCyclingLabelTransitionEffectScrollUp   = 1 << 4,
    BBCyclingLabelTransitionEffectScrollDown = 1 << 5,

    BBCyclingLabelTransitionEffectDefault = BBCyclingLabelTransitionEffectCrossFade
} BBCyclingLabelTransitionEffect;



#pragma mark - Custom types

typedef void(^BBCyclingLabelPreTransitionBlock)(UILabel* labelToEnter);
typedef void(^BBCyclingLabelTransitionBlock)(UILabel* labelToExit, UILabel* labelToEnter);



#pragma mark -

@interface BBCyclingLabel : UIView


#pragma mark Public properties

@property(assign, nonatomic) BBCyclingLabelTransitionEffect   transitionEffect;
@property(copy,   nonatomic) BBCyclingLabelPreTransitionBlock preTransitionBlock;
@property(copy,   nonatomic) BBCyclingLabelTransitionBlock    transitionBlock;
@property(assign, nonatomic) NSTimeInterval                   transitionDuration;
// Same properties as UILabel, these will be propagated to the underlying labels
@property(copy,   nonatomic) NSString*            text;
@property(strong, nonatomic) UIFont*              font;
@property(strong, nonatomic) UIColor*             textColor;
@property(strong, nonatomic) UIColor*             shadowColor;
@property(assign, nonatomic) CGSize               shadowOffset;
@property(assign, nonatomic) UITextAlignment      textAlignment;
@property(assign, nonatomic) UILineBreakMode      lineBreakMode;
@property(assign, nonatomic) NSInteger            numberOfLines;
@property(assign, nonatomic) BOOL                 adjustsFontSizeToFitWidth;
@property(assign, nonatomic) CGFloat              minimumFontSize;
@property(assign, nonatomic) UIBaselineAdjustment baselineAdjustment;


#pragma mark Creation

- (id)initWithFrame:(CGRect)frame andTransitionType:(BBCyclingLabelTransitionEffect)transitionEffect;


#pragma mark Public methods

/*! Sets the text for the next label and performs a transition between current and next label (if animated is YES) */
- (void)setText:(NSString*)text animated:(BOOL)animated;

@end
//
// Copyright 2012 BiasedBit
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//
//  Created by Bruno de Carvalho -- @biasedbit / http://biasedbit.com
//  Copyright (c) 2012 BiasedBit. All rights reserved.
//

#import "BBCyclingLabel.h"



#pragma mark - Constants

NSTimeInterval const kBBCyclingLabelDefaultTransitionDuration = 0.3;



#pragma mark -

@interface BBCyclingLabel ()
{
    NSUInteger _currentLabelIndex;
}


#pragma mark Private properties

@property(strong, nonatomic) NSArray* labels;
@property(strong, nonatomic) UILabel* currentLabel;


#pragma mark Private helpers

- (void)setupWithEffect:(BBCyclingLabelTransitionEffect)effect andDuration:(NSTimeInterval)duration;
- (void)prepareTransitionBlocks;
- (NSUInteger)nextLabelIndex;
- (void)resetLabel:(UILabel*)label;

@end



#pragma mark -

@implementation BBCyclingLabel


#pragma mark Property synthesizers

@synthesize transitionEffect   = _transitionEffect;
@synthesize preTransitionBlock = _preTransitionBlock;
@synthesize transitionBlock    = _transitionBlock;
@synthesize transitionDuration = _transitionDuration;
// Private
@synthesize labels       = _labels;
@synthesize currentLabel = _currentLabel;


#pragma mark Creation

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self != nil) {
        [self setupWithEffect:BBCyclingLabelTransitionEffectDefault
                  andDuration:kBBCyclingLabelDefaultTransitionDuration];
    }

    return self;
}

- (id)initWithCoder:(NSCoder*)coder
{
    self = [super initWithCoder:coder];
    if (self != nil) {
        [self setupWithEffect:BBCyclingLabelTransitionEffectDefault
                  andDuration:kBBCyclingLabelDefaultTransitionDuration];
    }

    return self;
}

- (id)initWithFrame:(CGRect)frame andTransitionType:(BBCyclingLabelTransitionEffect)transitionEffect;
{
    self = [super initWithFrame:frame];
    if (self != nil) {
        [self setupWithEffect:transitionEffect
                  andDuration:kBBCyclingLabelDefaultTransitionDuration];
    }

    return self;
}


#pragma mark Manual property accessors

- (void)setTransitionEffect:(BBCyclingLabelTransitionEffect)transitionEffect
{
    _transitionEffect = transitionEffect;
    [self prepareTransitionBlocks];
}

- (NSString*)text
{
    return _currentLabel.text;
}

- (void)setText:(NSString*)text
{
    [self setText:text animated:YES];
}

- (UIFont*)font
{
    return _currentLabel.font;
}

- (void)setFont:(UIFont*)font
{
    for (UILabel* label in _labels) {
        label.font = font;
    }
}

- (UIColor*)textColor
{
    return _currentLabel.textColor;
}

- (void)setTextColor:(UIColor*)textColor
{
    for (UILabel* label in _labels) {
        label.textColor = textColor;
    }
}

- (UIColor*)shadowColor
{
    return _currentLabel.shadowColor;
}

- (void)setShadowColor:(UIColor*)shadowColor
{
    for (UILabel* label in _labels) {
        label.shadowColor = shadowColor;
    }
}

- (CGSize)shadowOffset
{
    return _currentLabel.shadowOffset;
}

- (void)setShadowOffset:(CGSize)shadowOffset
{
    for (UILabel* label in _labels) {
        label.shadowOffset = shadowOffset;
    }
}

- (UITextAlignment)textAlignment
{
    return _currentLabel.textAlignment;
}

- (void)setTextAlignment:(UITextAlignment)textAlignment
{
    for (UILabel* label in _labels) {
        label.textAlignment = textAlignment;
    }
}

- (UILineBreakMode)lineBreakMode
{
    return _currentLabel.lineBreakMode;
}

- (void)setLineBreakMode:(UILineBreakMode)lineBreakMode
{
    for (UILabel* label in _labels) {
        label.lineBreakMode = lineBreakMode;
    }
}

- (NSInteger)numberOfLines
{
    return _currentLabel.numberOfLines;
}

- (void)setNumberOfLines:(NSInteger)numberOfLines
{
    for (UILabel* label in _labels) {
        label.numberOfLines = numberOfLines;
    }
}

- (BOOL)adjustsFontSizeToFitWidth
{
    return _currentLabel.adjustsFontSizeToFitWidth;
}

- (void)setAdjustsFontSizeToFitWidth:(BOOL)adjustsFontSizeToFitWidth
{
    for (UILabel* label in _labels) {
        label.adjustsFontSizeToFitWidth = adjustsFontSizeToFitWidth;
    }
}

- (CGFloat)minimumFontSize
{
    return _currentLabel.minimumFontSize;
}

- (void)setMinimumFontSize:(CGFloat)minimumFontSize
{
    for (UILabel* label in _labels) {
        label.minimumFontSize = minimumFontSize;
    }
}

- (UIBaselineAdjustment)baselineAdjustment
{
    return _currentLabel.baselineAdjustment;
}

- (void)setBaselineAdjustment:(UIBaselineAdjustment)baselineAdjustment
{
    for (UILabel* label in _labels) {
        label.baselineAdjustment = baselineAdjustment;
    }
}


#pragma mark Public methods

- (void)setText:(NSString*)text animated:(BOOL)animated
{
    NSUInteger nextLabelIndex = [self nextLabelIndex];
    UILabel* nextLabel = [_labels objectAtIndex:nextLabelIndex];
    UILabel* previousLabel = _currentLabel;

    nextLabel.text = text;
    // Resetting the label state ensures we can change the transition type without extra code on pre-transition block.
    // Without it a transition that has no alpha changes would have to ensure alpha = 1 on pre-transition block (as
    // well as with every other possible animatable property)
    [self resetLabel:nextLabel];

    // Update both current label index and current label pointer
    self.currentLabel = nextLabel;
    _currentLabelIndex = nextLabelIndex;

    // Prepare the next label before the transition animation
    if (_preTransitionBlock != nil) {
        _preTransitionBlock(nextLabel);
    } else {
        // If no pre-transition block is set, prepare the next label for a cross-fade
        nextLabel.alpha = 0;
    }

    // Unhide the label that's about to be shown
    nextLabel.hidden = NO;

    void (^changeBlock)() = ^() {
        // Perform the user provided changes
        if (_transitionBlock != nil) {
            _transitionBlock(previousLabel, nextLabel);
        } else {
            // If no transition block is set, perform a simple cross-fade
            previousLabel.alpha = 0;
            nextLabel.alpha = 1;
        }
    };

    void (^completionBlock)(BOOL) = ^(BOOL finished) {
        if (finished) {
            // TODO this is kind of bugged since all transitions that include affine transforms always return finished
            // as true, even when it doesn't finish...
            previousLabel.hidden = YES;
        }
    };

    if (animated) {
        // Animate the transition between both labels
        [UIView animateWithDuration:_transitionDuration animations:changeBlock completion:completionBlock];
    } else {
        changeBlock();
        completionBlock(YES);
    }
}


#pragma mark Private helpers

- (void)setupWithEffect:(BBCyclingLabelTransitionEffect)effect andDuration:(NSTimeInterval)duration
{
    NSUInteger size = 2;
    NSMutableArray* labels = [NSMutableArray arrayWithCapacity:size];
    for (NSUInteger i = 0; i < size; i++) {
        UILabel* label = [[UILabel alloc] initWithFrame:self.bounds];
        [self addSubview:label];
        label.backgroundColor = [UIColor clearColor];
        label.hidden = YES;
        label.numberOfLines = 0;

        [labels addObject:label];
    }

    _currentLabelIndex = 0;
    self.currentLabel = [labels objectAtIndex:0];
    self.labels = labels;

    _currentLabel.hidden = NO;

    self.transitionEffect = effect;
    self.transitionDuration = duration;
}

- (void)prepareTransitionBlocks
{
    //if matches custom
    if (_transitionEffect == BBCyclingLabelTransitionEffectCustom) {
        return;
    }

    BBCyclingLabelTransitionEffect type = _transitionEffect;
    self.preTransitionBlock = ^(UILabel* labelToEnter) {
        if (type & BBCyclingLabelTransitionEffectFadeIn) {
            labelToEnter.alpha = 0;
        }

        if (type & BBCyclingLabelTransitionEffectZoomIn) {
            labelToEnter.transform = CGAffineTransformMakeScale(0.5, 0.5);
        }

        if (type & (BBCyclingLabelTransitionEffectScrollUp | BBCyclingLabelTransitionEffectScrollDown)) {
            CGRect frame = labelToEnter.frame;

            if (type & BBCyclingLabelTransitionEffectScrollUp) {
                frame.origin.y = self.bounds.size.height;
            }

            if (type & BBCyclingLabelTransitionEffectScrollDown) {
                frame.origin.y = 0 - frame.size.height;
            }
            labelToEnter.frame = frame;
        }
    };
    self.transitionBlock = ^(UILabel* labelToExit, UILabel* labelToEnter) {
        if (type & BBCyclingLabelTransitionEffectFadeIn) {
            labelToEnter.alpha = 1;
        }

        if (type & BBCyclingLabelTransitionEffectFadeOut) {
            labelToExit.alpha = 0;
        }

        if (type & BBCyclingLabelTransitionEffectZoomOut) {
            labelToExit.transform = CGAffineTransformMakeScale(1.5, 1.5);
        }

        if (type & BBCyclingLabelTransitionEffectZoomIn) {
            labelToEnter.transform = CGAffineTransformIdentity;
        }

        if (type & (BBCyclingLabelTransitionEffectScrollUp | BBCyclingLabelTransitionEffectScrollDown)) {
            CGRect frame = labelToExit.frame;
            CGRect enterFrame = labelToEnter.frame;

            if (type & BBCyclingLabelTransitionEffectScrollUp) {
                frame.origin.y = 0 - frame.size.height; 
                enterFrame.origin.y = roundf((self.bounds.size.height / 2) - (enterFrame.size.height / 2));
            }

            if (type & BBCyclingLabelTransitionEffectScrollDown) {
                frame.origin.y = self.bounds.size.height;
                enterFrame.origin.y = roundf((self.bounds.size.height / 2) - (enterFrame.size.height / 2));
            }

            labelToExit.frame = frame;
            labelToEnter.frame = enterFrame;
        }
    };
}

- (NSUInteger)nextLabelIndex
{
    return (_currentLabelIndex + 1) % [_labels count];
}

- (void)resetLabel:(UILabel*)label
{
    label.alpha = 1;
    label.transform = CGAffineTransformIdentity;
    label.frame = self.bounds;
}

@end

你可能感兴趣的:(动画)