#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface WSMarqueeLabel : UIView
@property (nonatomic, assign) CGFloat speed;
@property (nonatomic, assign) CGFloat showTextTime;
@property (nullable, nonatomic, copy) NSString *text;
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, strong) UIFont *font;
/// 开启滚动,默认为 YES。当 enableScroll 为 YES 时,如果文字超出,则自动开始滚动。设置为 NO,则不滚动。
/// 像普通 Label 一样会压缩显示。
@property (nonatomic, assign) BOOL enableScroll;
- (void)startAnimation;
@end
NS_ASSUME_NONNULL_END
#import "WSMarqueeLabel.h"
#import "UIFont+CustomFont.h"
@interface WSMarqueeLabel ()
@property (nonatomic, strong) UILabel *label1;
@property (nonatomic, strong) UILabel *label2;
@property (nonatomic, strong) UIView *container;
@end
@implementation WSMarqueeLabel
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initUI];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (NSString *)text
{
return self.label1.text;
}
- (void)setText:(NSString *)text
{
self.label1.text = self.label2.text = text;
[self layoutSubviews];
}
- (UIColor *)textColor
{
return self.label1.textColor;
}
- (void)setTextColor:(UIColor *)textColor
{
self.label1.textColor = self.label2.textColor = textColor;
}
- (UIFont *)font
{
return self.label1.font;
}
- (void)setFont:(UIFont *)font
{
self.label1.font = self.label2.font = font;
}
- (CGSize)intrinsicContentSize
{
return self.label1.intrinsicContentSize;
}
#define WSMarqueeLabel_Text_Space 16
- (void)initUI
{
_enableScroll = YES;
self.label1 = [[UILabel alloc] init];
self.label2 = [[UILabel alloc] init];
self.label1.backgroundColor = [UIColor clearColor];
self.label2.backgroundColor = [UIColor clearColor];
self.textColor = [UIColor whiteColor];
self.font = [UIFont wsfont_textRegular];
UIView *container = [[UIView alloc] init];
[container addSubview:self.label1];
[container addSubview:self.label2];
[self addSubview:container];
self.container = container;
self.layer.masksToBounds = YES;
self.speed = 30;
self.showTextTime = 2;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startAnimation) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)startAnimation
{
[self setNeedsLayout];
}
- (void)setSpeed:(CGFloat)speed
{
if (speed == 0) {
speed = 30;
}
_speed = speed;
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.enableScroll) {
[self.label1 sizeToFit];
[self.label2 sizeToFit];
CGFloat width = self.label1.frame.size.width;
CGFloat height = self.label1.frame.size.height;
self.label1.frame = CGRectMake(0, 0, width, height);
self.label2.frame = CGRectMake(width + WSMarqueeLabel_Text_Space, 0, width, height);
self.container.frame = CGRectMake(0, 0, width * 2 + WSMarqueeLabel_Text_Space, height);
[self updateAndScroll];
} else {
self.label1.frame = self.bounds;
self.container.frame = self.bounds;
[self stopScroll];
}
}
- (void)willMoveToWindow:(UIWindow *)newWindow
{
if (newWindow == nil) {
[self stopScroll];
}
}
- (void)didMoveToWindow
{
if (self.window == nil) {
[self stopScroll];
} else {
[self updateAndScroll];
}
}
- (void)stopScroll
{
[self.container.layer removeAllAnimations];
self.container.frame = CGRectMake(0, CGRectGetMinY(self.container.frame), CGRectGetWidth(self.container.frame), CGRectGetHeight(self.container.frame));
self.label2.hidden = YES;
}
- (void)updateAndScroll
{
[self.container.layer removeAllAnimations];
self.container.frame = CGRectMake(0, CGRectGetMinY(self.container.frame), CGRectGetWidth(self.container.frame), CGRectGetHeight(self.container.frame));
CGFloat labelWidth = self.label1.frame.size.width;
if (labelWidth <= self.bounds.size.width || !self.enableScroll) {
self.label2.hidden = YES;
return;
}
self.label2.hidden = NO;
CGRect fromRect = self.container.frame;
CGRect toRect = fromRect;
toRect.origin.x = 0 - labelWidth - WSMarqueeLabel_Text_Space;
CGFloat duration = (labelWidth + WSMarqueeLabel_Text_Space) / self.speed;
duration = fmin(duration, 20);
[self repeatAnimationWithDuration:duration delay:1 fromRect:fromRect toRect:toRect];
}
- (void)repeatAnimationWithDuration:(CGFloat)duration delay:(CGFloat)delay fromRect:(CGRect)fromRect toRect:(CGRect)toRect
{
self.container.frame = fromRect;
[UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveLinear animations:^{
self.container.frame = toRect;
} completion:^(BOOL finished) {
if (finished) {
[self updateAndScroll];
}
}];
}
- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis
{
return [self.label1 contentCompressionResistancePriorityForAxis:axis];
}
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis
{
[self.label1 setContentCompressionResistancePriority:priority forAxis:axis];
}
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis
{
return [self.label1 contentHuggingPriorityForAxis:axis];
}
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis
{
[self.label1 setContentHuggingPriority:priority forAxis:axis];
}
@end
网友评论