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.
165 lines
4.8 KiB
165 lines
4.8 KiB
![]()
2 years ago
|
//
|
||
|
// 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
|