You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

164 lines
4.8 KiB

//
// SLMarqueeControl.m
// SLMarqueeControl
//
// Created by sl on 2018/10/24.
// Copyright © 2018年 WSonglin. All rights reserved.
//
#import "SLMarqueeControl.h"
static CGFloat const kLabelOffset = 20.f;
@interface SLMarqueeControl ()
@property (nonatomic, weak) UIView *innerContainer;
@property (nonatomic, weak) UILabel *label;
@end
@implementation SLMarqueeControl
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.clipsToBounds = YES;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil
];
[self.marqueeLabel addObserver:self
forKeyPath:@"text"
options:NSKeyValueObservingOptionNew
context:nil
];
[self.marqueeLabel addObserver:self
forKeyPath:@"attributedText"
options:NSKeyValueObservingOptionNew
context:nil
];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)willMoveToWindow:(UIWindow *)newWindow {
if (newWindow) {
[self startAnimation];
}
[super willMoveToWindow:newWindow];
}
+ (BOOL)accessInstanceVariablesDirectly {
return NO;
}
#pragma mark - NSNotification
- (void)appBecomeActive:(NSNotification *)note {
[self startAnimation];
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
[self startAnimation];
}
#pragma mark - Private method
- (void)startAnimation {
if (0 == CGRectGetWidth(self.bounds)
|| 0 == CGRectGetHeight(self.bounds)) {
return;
}
[self.innerContainer.layer removeAnimationForKey:@"Marquee"];
[self bringSubviewToFront:self.innerContainer];
CGSize size = [self evaluateMarqueeLabelContentSize];
for (UIView *view in self.innerContainer.subviews) {
if ([view isKindOfClass:[UILabel class]]) {
[view removeFromSuperview];
}
}
CGRect rect = CGRectMake(0.f, 0.f, size.width + kLabelOffset, CGRectGetHeight(self.bounds));
UILabel *label = [[UILabel alloc] initWithFrame:rect];
label.backgroundColor = [UIColor clearColor];
label.text = self.marqueeLabel.text;
label.attributedText = self.marqueeLabel.attributedText;
[self.innerContainer addSubview:label];
if (size.width > CGRectGetWidth(self.bounds)) {
CGRect nextRect = rect;
nextRect.origin.x = size.width + kLabelOffset;
UILabel *nextLabel = [[UILabel alloc] initWithFrame:nextRect];
nextLabel.backgroundColor = [UIColor clearColor];
nextLabel.text = self.marqueeLabel.text;
nextLabel.attributedText = self.marqueeLabel.attributedText;
[self.innerContainer addSubview:nextLabel];
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
animation.keyTimes = @[@0.f, @1.f];
animation.duration = size.width / 50.f;
animation.values = @[@0, @(-(size.width + kLabelOffset))];
animation.repeatCount = INT16_MAX;
animation.timingFunction = [CAMediaTimingFunction functionWithName:@"linear"];
[self.innerContainer.layer addAnimation:animation forKey:@"Marquee"];
} else {
label.frame = self.bounds;
}
}
- (CGSize)evaluateMarqueeLabelContentSize {
CGSize size = CGSizeZero;
if (self.marqueeLabel && self.marqueeLabel.text.length > 0) {
size = [self.marqueeLabel.text sizeWithAttributes:@{NSFontAttributeName:self.marqueeLabel.font}];
}
return size;
}
#pragma mark - Getter
- (UILabel *)marqueeLabel {
return self.label;
}
- (UIView *)innerContainer {
if (!_innerContainer) {
UIView *view = [[UIView alloc] initWithFrame:self.bounds];
view.backgroundColor = [UIColor clearColor];
view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addSubview:view];
_innerContainer = view;
}
return _innerContainer;
}
- (UILabel *)label {
if (!_label) {
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor clearColor];
label.font = Font_(12);
label.textColor = RGB(133, 133, 133);
[self addSubview:label];
_label = label;
}
return _label;
}
@end