美文网首页笔记篇
简易的跑马灯

简易的跑马灯

作者: 失忆的程序员 | 来源:发表于2021-08-13 16:59 被阅读0次

给你们来张图看看先

简易的跑🏃.png

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];
    }
    
}

相关文章

  • 简易的跑马灯

    给你们来张图看看先 用 Masonry 布局,自己算Frame 也行,我把自己算Frame 注释掉了。 创建一个 ...

  • iOS 跑马灯

    简易跑马灯效果,代码简单易懂,适合初学者 /** 新建文件,继承于UIView .h文件代码如下*/ #impor...

  • jquery 简易跑马灯

    思路: 1.css 需要的两种切换样式 .circle和.circle_active 2.设置定时器 带参数 倒计...

  • iOS-跑马灯效果实现

    跑马灯效果在移动客户端中多用于“公告”、“消息”等功能的展示,本次demo以一种简易的实现方法(UILabel...

  • 类似京东快报文字跑马灯效果

    商城类App基本都会需要这种跑马灯(上下切换效果),这里简易实现了一下。 主要代码 注:使用的时候只需要传入我们要...

  • GitHub上受欢迎的Android UI Library(下)

    跑马灯 MarqueeView★1568 - 垂直翻页公告 MarqueeViewDemo★896 - 跑马灯Vi...

  • textview - 跑马灯

    textview 的跑马灯不用说了吧,大家肯定都知道这是个啥,但是呢我还是放个图吧: 实现单个跑马灯 跑马灯的核心...

  • Android 基础 UI 之 TextView

    一、显示富文本 效果图image 布局文件 逻辑代码 二、跑马灯效果 1. 横向跑马灯 效果图: 单个实现跑马灯:...

  • iOS 跑马灯的实现

    介绍 我们一说起跑马灯第一个想到的就是:山寨机。接下来介绍的跑马灯和那个跑马灯是不一样滴。在iOS中,跑马灯是指l...

  • Android 图文垂直跑马灯

    最近在维护老项目,老项目有一个地方需要修改,就是垂直跑马灯的问题,之前的垂直跑马灯是只有文字跑马灯,新版需要加上。...

网友评论

    本文标题:简易的跑马灯

    本文链接:https://www.haomeiwen.com/subject/dxqjbltx.html