跑马灯Label

跑马灯Label网上有很多个做法,其实基本原理很简单,做法也很多样,可以是一个scrollView上面放两个label,然后用定时器定时执行动画;也有的是用定时器,在短暂的间隔时间内执行把文字drawInRect方法。

最开始我是用上面说的第一种方法,但是发现每次定时器执行完一次动画,下一次动画执行之间,总会有个很短暂但很明显感觉到的停顿,这和我想要的效果不同;而执行文字drawInRect方法是比较耗cpu的,第二个方法对性能消耗太大了;既然最终都是执行动画,那么为什么不让动画自己来负责自己的开始和结束和循环,而让定时器都不用参与?


我的做法里主要用了CATextLayer和CABasicAnimation,CATextLayer是用来绘制文本,CABasicAnimation用来执行动画,CATextLayer和UILabel很相似,在iOS6之前,UILabel是通过Webkit来实现绘制的,所以当很多文字的时候性能方面就有压力,而CATextLayer是使用了CoreText,渲染非常快。

CATextLayer有个string的属性,这个属性可以是NSString也可以是NSAttributedString,但当是NSAttributedString的时候,相应的像font属性之类的属性就没有效果。

我在使用CATextLayer的时候,碰上了一点麻烦,就是字体,CATextLayer使用的不是UIFont,而是CTFontRef和CGFontRef或者给字体的名称,这三个方法我都试过,但在最终效果上对比同样文本和字体的UILabel,计算出来的宽度总是有小偏差,所以最终使用了string属性是NSAttributedString对象(这里个人猜测,可能即使string属性是NSString对象,最终也是转换为NSAttributedString来使用)。


下面是我的做法

@interface AutoScrollLabel : UIView

@property (nonatomic, copy) NSString* text;
@property (nonatomic, assign) CGFloat fontSize;
@property (nonatomic, strong) UIFont* font;
@property (nonatomic, strong) UIColor* textColor;
@property (nonatomic, assign) CGFloat speed;

@property (nonatomic, copy) NSAttributedString* attributedText;

@end

#import <CoreText/CoreText.h>

@interface AutoScrollLabel() {
    
    CATextLayer* _firstLayer;
    CATextLayer* _secondLayer;
    
}

@end

@implementation AutoScrollLabel

- (instancetype)init {
    
    self = [super init];
    if (self) {
        [self commonInit];
    }
    return self;
    
}

- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
        [self commonInit];
    }
    return  self;
    
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self commonInit];
    }
    return self;
    
}

- (void)commonInit {
    
    _firstLayer = [[CATextLayer alloc] init];
    _firstLayer.bounds = CGRectZero;
    _firstLayer.position = CGPointZero;
    _firstLayer.alignmentMode = kCAAlignmentCenter;
    _firstLayer.foregroundColor = [UIColor blackColor].CGColor;
    _firstLayer.contentsScale = [UIScreen mainScreen].scale;
    //contentsScale的指定为了适配retian屏
    [self.layer addSublayer:_firstLayer];
    
    _secondLayer = [[CATextLayer alloc] init];
    _secondLayer.bounds = CGRectZero;
    _secondLayer.position = CGPointZero;
    _secondLayer.alignmentMode = kCAAlignmentCenter;
    _secondLayer.foregroundColor = [UIColor blackColor].CGColor;
    _secondLayer.contentsScale = [UIScreen mainScreen].scale;
    [self.layer addSublayer:_secondLayer];
    
    _fontSize = 15.0f;
    _font = [UIFont systemFontOfSize:_fontSize];
    _textColor = [UIColor blackColor];
    
    self.layer.masksToBounds = YES;
    
}

- (void)setAttributedText:(NSAttributedString *)attributedText {
    
    _attributedText = attributedText;
    _firstLayer.string = attributedText;
    _secondLayer.string = attributedText;
    
}

- (void)drawRect:(CGRect)rect {
    
    if (_attributedText == nil) {
        
        _font = [UIFont systemFontOfSize:_fontSize];
        
        _attributedText = [[NSAttributedString alloc] initWithString:_text attributes:@{NSFontAttributeName:_font, NSForegroundColorAttributeName:_textColor}];
        
        _firstLayer.string = _attributedText;
        _secondLayer.string = _attributedText;
        
    }
    
    NSRange range = NSMakeRange(0, _attributedText.length);
    CGSize textSize = [_attributedText.string boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
                        options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                     attributes:[_attributedText attributesAtIndex:0 effectiveRange:&range]
                        context:nil].size;
    
    
    if (textSize.width < rect.size.width) {
        textSize.width = rect.size.width;
    }
    
    // 在计算出的文本宽度后加入10的宽度作为两个文本之间的间隔
    _firstLayer.bounds = CGRectMake(0, 0, textSize.width + 10, textSize.height);
    _firstLayer.position = CGPointMake(textSize.width / 2 + 5, rect.size.height / 2);
    
    _secondLayer.bounds = CGRectMake(0, 0, textSize.width + 10, textSize.height);
    _secondLayer.position = CGPointMake(textSize.width + 10 + textSize.width / 2 + 5, rect.size.height / 2);
    
    // 文本宽度超过区域宽度才有滚动动画
    if (textSize.width > rect.size.width) {
        
        if (_speed <= 0) {
            _speed = textSize.width / 30;
        }
    
        CABasicAnimation* firstAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
        firstAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(_firstLayer.frame.origin.x - textSize.width / 2 - 5, rect.size.height / 2)];
        firstAnimation.duration = _speed;
        firstAnimation.repeatCount = HUGE_VALF;
        [_firstLayer addAnimation:firstAnimation forKey:@"FirstAnimation"];
        
        CABasicAnimation* secondAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
        secondAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(textSize.width / 2 + 5, rect.size.height / 2)];
        secondAnimation.duration = _speed;
        secondAnimation.repeatCount = HUGE_VALF;
        [_secondLayer addAnimation:secondAnimation forKey:@"SecondAnimation"];
        
    }
}

@end


用xib生成的实例也是有效

@property (weak, nonatomic) IBOutlet AutoScrollLabel *autoScrollLabel;
/只是作为分割线
_autoScrollLabel.text = @"jojo_text店铺";
_autoScrollLabel.fontSize = 17;


但跟CATextLayer一样,如果指定了attributedText属性,那么其他属性设置就无需了。

转载于:https://my.oschina.net/u/574245/blog/552295

内容概要:2025年大宗商品市场展望报告由世界银行发布,分析了能源、农业、金属和矿物、贵金属以及化肥等多个主要商品类别的市场发展与前景。报告指出,由于全球经济增长放缓和贸易紧张加剧,2025年大宗商品价格预计总体下降12%,2026年进一步下降5%,达到六年来的最低点。油价预计2025年平均为每桶64美元,2026年降至60美元,主要受全球石油消费放缓和供应增加的影响。农业商品价格预计2025年基本稳定,2026年下降3%,其中粮食和原材料价格分别下降7%和2%,但饮料价格上涨20%。金属价格预计2025年下降10%,2026年再降3%,特别是铜和铝价格将显著下跌。贵金属如黄金和白银因避险需求强劲,预计价格将继续上涨。报告还特别关注了疫情后大宗商品周期的变化,指出周期变得更短、更剧烈,主要受到宏观经济冲击、极端天气事件和地缘政治冲突的影响。 适用人群:对全球经济趋势、大宗商品市场动态及其对不同经济体影响感兴趣的政策制定者、投资者、分析师及研究机构。 使用场景及目标:①帮助政策制定者评估全球经济增长放缓对大宗商品市场的影响,从而调整经济政策;②为投资者提供有关未来大宗商品价格走势的风险提示,以便进行投资决策;③协助分析师和研究机构深入理解疫情后大宗商品市场的周期特征,识别潜在的投资机会和风险。 其他说明:报告强调,全球经济增长放缓、贸易紧张加剧以及地缘政治不确定性是影响大宗商品价格的主要因素。此外,极端天气事件和能源转型也对农业和能源商品市场产生了深远影响。报告呼吁各方关注这些结构性变化,并采取相应的风险管理措施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值