给你们来张图看看先

用 Masonry 布局,自己算Frame 也行,我把自己算Frame 注释掉了。
创建一个 自己的View 继承自 UIView 或者自己的 公共BaseView;
不多说上代码,走起
.h 这里的 "XPaoMaDView" 是我的自定义名称
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface XPaoMaDView : UIView
///
//- (instancetype)initWithFrame:(CGRect)frame withTitle:(NSString *)title;
///
- (void)withTitle:(NSString *)title;
///
- (void)start;
///
- (void)stop;
@end
NS_ASSUME_NONNULL_END
//
#import "XPaoMaDView.h"
// 单次循环的时间
static const NSInteger animationDuration = 15;
// 文字大小
static const NSInteger textFont = 14.0;
@interface XPaoMaDView()
<
CAAnimationDelegate
>
{
//左侧label的frame
CGRect currentFrame;
//右侧label的frame
CGRect behindFrame;
//存放左右label的数组
NSMutableArray *labelArray;
//label的高度
CGFloat labelHeight;
//是否为暂停状态
BOOL isStop;
}
@end
@implementation XPaoMaDView
/*
- (instancetype)initWithFrame:(CGRect)frame withTitle:(NSString *)title
{
self = [super initWithFrame:frame];
if (self) {
self.clipsToBounds = YES;
//
CGFloat viewHeight = frame.size.height;
labelHeight = viewHeight;
//
UILabel *myLable = [[UILabel alloc] init];
myLable.text = title;
myLable.font = [UIFont systemFontOfSize:textFont];
myLable.backgroundColor = [UIColor orangeColor];
//计算文本的宽度
CGFloat calcuWidth = [self widthForTextString:title height:labelHeight fontSize:textFont];
//这两个frame很重要 分别记录的是左右两个label的frame 而且后面也会需要到这两个frame
currentFrame = CGRectMake(0, 0, calcuWidth, labelHeight);
behindFrame = CGRectMake(currentFrame.origin.x + currentFrame.size.width, 0, calcuWidth, labelHeight);
myLable.frame = currentFrame;
[self addSubview:myLable];
labelArray = [NSMutableArray arrayWithObject:myLable];
//如果文本的宽度大于视图的宽度才开始跑
if (calcuWidth > frame.size.width)
{
UILabel *behindLabel = [[UILabel alloc] init];
behindLabel.frame = behindFrame;
behindLabel.text = title;
behindLabel.font = [UIFont systemFontOfSize:textFont];
behindLabel.backgroundColor = [UIColor orangeColor];
[labelArray addObject:behindLabel];
[self addSubview:behindLabel];
[self doCustomAnimation];
}
}
return self;
}
*/
///
- (void)withTitle:(NSString *)title
{
// 注意 layoutIfNeeded 这里使用的是 Masonry 要加这句话,不然你懂得
[self layoutIfNeeded]; //
self.clipsToBounds = YES;
//
CGFloat viewHeight = self.frame.size.height;
labelHeight = viewHeight;
//
UILabel *myLable = [[UILabel alloc] init];
myLable.text = title;
myLable.font = [UIFont systemFontOfSize:textFont];
myLable.backgroundColor = [UIColor orangeColor];
//计算文本的宽度
CGFloat calcuWidth = [self widthForTextString:title height:labelHeight fontSize:textFont];
//这两个frame很重要 分别记录的是左右两个label的frame 而且后面也会需要到这两个frame
currentFrame = CGRectMake(0, 0, calcuWidth, labelHeight);
behindFrame = CGRectMake(currentFrame.origin.x + currentFrame.size.width, 0, calcuWidth, labelHeight);
myLable.frame = currentFrame;
[self addSubview:myLable];
labelArray = [NSMutableArray arrayWithObject:myLable];
//如果文本的宽度大于视图的宽度才开始跑
if (calcuWidth > self.frame.size.width)
{
UILabel *behindLabel = [[UILabel alloc] init];
behindLabel.frame = behindFrame;
behindLabel.text = title;
behindLabel.font = [UIFont systemFontOfSize:textFont];
behindLabel.backgroundColor = [UIColor orangeColor];
[labelArray addObject:behindLabel];
[self addSubview:behindLabel];
[self doCustomAnimation];
}
}
- (void)doCustomAnimation
{
//取到两个label
UILabel *lableOne = [labelArray firstObject];
UILabel *lableTwo = [labelArray lastObject];
[lableOne.layer removeAnimationForKey:@"LabelOneAnimation"];
[lableTwo.layer removeAnimationForKey:@"LabelTwoAnimation"];
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.values = @[
[NSValue valueWithCGPoint:CGPointMake(lableOne.frame.origin.x + currentFrame.size.width / 2, lableOne.frame.origin.y + labelHeight / 2)],
[NSValue valueWithCGPoint:CGPointMake(lableOne.frame.origin.x - currentFrame.size.width / 2, lableOne.frame.origin.y + labelHeight / 2)]
];
animation.duration = animationDuration;
animation.delegate = self;
animation.calculationMode = kCAAnimationLinear;
animation.removedOnCompletion = NO;
[lableOne.layer addAnimation:animation forKey:@"LabelOneAnimation"];
CAKeyframeAnimation *animationTwo = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animationTwo.values = @[
[NSValue valueWithCGPoint:CGPointMake(lableTwo.frame.origin.x + currentFrame.size.width / 2, lableTwo.frame.origin.y + labelHeight / 2)],
[NSValue valueWithCGPoint:CGPointMake(lableTwo.frame.origin.x - currentFrame.size.width / 2, lableTwo.frame.origin.y + labelHeight / 2)]
];
animationTwo.duration = animationDuration;
animationTwo.delegate = self;
animationTwo.removedOnCompletion = NO;
animationTwo.calculationMode = kCAAnimationLinear;
[lableTwo.layer addAnimation:animationTwo forKey:@"LabelTwoAnimation"];
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
UILabel *lableOne = [labelArray firstObject];
UILabel *lableTwo = [labelArray lastObject];
if (flag && anim == [lableOne.layer animationForKey:@"LabelOneAnimation"])
{
//两个label水平相邻摆放 内容一样 label1为初始时展示的 label2位于界面的右侧,未显示出来
//当完成动画时,即第一个label在界面中消失,第二个label位于第一个label的起始位置时,把第一个label放置到第二个label的初始位置
lableOne.frame = behindFrame;
lableTwo.frame = currentFrame;
//在数组中将第一个label放置到右侧,第二个label放置到左侧(因为此时展示的就是labelTwo)
[labelArray replaceObjectAtIndex:1 withObject:lableOne];
[labelArray replaceObjectAtIndex:0 withObject:lableTwo];
[self doCustomAnimation];
}
}
- (CGFloat) widthForTextString:(NSString *)tStr height:(CGFloat)tHeight fontSize:(CGFloat)tSize
{
NSDictionary *dict = @{NSFontAttributeName : [UIFont systemFontOfSize:tSize]};
CGRect rect = [tStr boundingRectWithSize:CGSizeMake(MAXFLOAT, tHeight) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];
return rect.size.width + 5;
}
- (void)start
{
if (isStop)
{
UILabel *lableOne = [labelArray firstObject];
[self resumeLayer:lableOne.layer];
UILabel *lableTwo = [labelArray lastObject];
[self resumeLayer:lableTwo.layer];
isStop = NO;
}
}
- (void)stop
{
if (!isStop)
{
UILabel *lableOne = [labelArray firstObject];
[self pauseLayer:lableOne.layer];
UILabel *lableTwo = [labelArray lastObject];
[self pauseLayer:lableTwo.layer];
isStop = YES;
}
}
//暂停动画
- (void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0;
layer.timeOffset = pausedTime;
}
//恢复动画
- (void)resumeLayer:(CALayer*)layer
{
//当你是停止状态时,则恢复
if (isStop)
{
CFTimeInterval pauseTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pauseTime;
layer.beginTime = timeSincePause;
}
}
@end
使用方法:
#import "XPaoMaDView.h"
///
@property (nonatomic, strong) XPaoMaDView *paomadengView;
// ---------------
- (void)这里就不要Copy了viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
调用UI啦🌶
[self addUI];
[self addBtnUI];
}
// ---------------
#pragma mark ----- lzy
- (XPaoMaDView *)paomadengView
{
if (!_paomadengView) {
_paomadengView = [[XPaoMaDView alloc] init];
}
return _paomadengView;
}
/// 添加 UI
- (void)addUI
{
[self.view addSubview:self.paomadengView];
[self.paomadengView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(RATIOA(20));
make.right.mas_equalTo(RATIOA(-20));
make.centerX.centerY.mas_equalTo(0);
make.height.mas_equalTo(RATIOA(44));
}];
self.paomadengView.backgroundColor = [UIColor 你给个颜色看看];
[self.paomadengView withTitle:@"1、这是个跑马灯,不信?你看~它跑起来了~~~2、这是个跑马灯,不信?你看~它跑起来了~~~"];
}
- (void)addBtnUI
{
NSArray *ary = @[@"开始", @"暂停"];
for (int i = 0; i < 2; i++) {
UIButton *btn = [[UIButton alloc] init];
[btn addTarget:self action:@selector(ActionClick:) forControlEvents:(UIControlEventTouchUpInside)];
[btn setTitle:ary[i] forState:(UIControlStateNormal)];
[btn setBackgroundColor:[UIColor 你给个颜色看看]];
btn.tag = 100 + i;
[self.view addSubview:btn];
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
if (i == 0) {
make.right.mas_equalTo(self.view.mas_centerX).offset(RATIOA(-20));
} else {
make.left.mas_equalTo(self.view.mas_centerX).offset(RATIOA(20));
}
make.top.mas_equalTo(RATIOA(100));
make.height.mas_equalTo(RATIOA(44));
make.width.mas_equalTo(RATIOA(100));
}];
}
}
- (void)ActionClick:(UIButton *)button
{
NSInteger index = button.tag - 100;
if (index == 0)
{
[self.paomadengView start];
}
else
{
[self.paomadengView stop];
}
}
网友评论