核心思想
1、通過UIView 開始動畫[UIView beginAnimations:@"scroll" context:nil];到提交動畫 [UIView commitAnimations]; 來實現動畫效果,在這代碼之間實現要做動畫的效果,中間可以設置動畫的速度,是否勻速及監聽。
2、通過設置偏移量來實現動畫效果,必須是滾動文字label超過父視圖才能滾動。
3、當完成一遍動畫后,判斷動畫是否完成及滾動文字寬度是否大於父視圖(理論上是大於的,要不怎么會進入代理方法),添加一個定時器實現繼續滾動,在這里實現停動效果。
4、放兩個label,並設置一定間距,這樣可以實現循環滾動的效果,通過數組創建UILabel *_label[2],當為向左時,初始位置是0,0 ;終點位置是第一個label的寬度+間距。
5、核心代碼
5.1 UIView beginAnimations的動畫
- (void)scroll{
//刪除之前的動畫,一定要加,否則外部將不能設置速度、間距及外部變量
[self.layer removeAllAnimations];
//初始位置
if (_dirtionType == DirtionTypeLeft) {
self.contentOffset = CGPointMake(0, 0);
}else if (_dirtionType == DirtionTypeRight){
self.contentOffset = CGPointMake(_label[0].frame.size.width+_labelBetweenGap, 0);
}
//開始動畫
[UIView beginAnimations:@"scroll" context:nil];
//動畫設置參數,代理,勻速,速度等
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:_label[0].frame.size.width/_speed];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
//animations
//終點位置
if (_dirtionType == DirtionTypeLeft) {
self.contentOffset = CGPointMake(_label[0].frame.size.width+_labelBetweenGap, 0);
}else if (_dirtionType == DirtionTypeRight){
self.contentOffset = CGPointMake(0, 0);
}
//完成動畫
[UIView commitAnimations];
}
//動畫完成調用
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finish context:(NSString *)context{
//動畫ID animationID,也就是上面scroll,可以設置多個動畫,這個animationID用來判斷不同動畫,finish.integerValue,如果為0時表示未完成,為1時表示已完成
if (finish.integerValue == 1 && _label[0].frame.size.width > self.frame.size.width) {
//pause time,動畫完成時,添加定時器,設置停留時間再滾動
[NSTimer scheduledTimerWithTimeInterval:_pauseTime target:self selector:@selector(scroll) userInfo:nil repeats:NO];
}
}
5.2 重新布局,設置滾動位置及決定是否可以滾動
- (void)rejustlabels{
//set labels frame 及self contentsize和is scroll
CGFloat offset = 0.0f;
for (NSInteger i = 0; i < NumLabels; i++) {
[_label[i] sizeToFit];
CGPoint center = _label[i].center;
center.y = self.center.y - self.frame.origin.y;
_label[i].center = center;
CGRect frame = _label[i].frame;
frame.origin.x = offset;
_label[i].frame = frame;
//每個label x的位置
offset += _label[i].frame.size.width+_labelBetweenGap;
}
CGSize size;
size.width = _label[0].frame.size.width+self.frame.size.width+_labelBetweenGap;
size.height = self.frame.size.height;
self.contentSize = size;
//判斷是否能滾動
if (_label[0].frame.size.width > self.frame.size.width) {
//show lab
for (NSInteger i = 1; i <NumLabels; i++) {
_label[i].hidden = NO;
}
[self scroll];
}else{//如果不能滾動,重新設置x的位置
for (NSInteger i = 1;i < NumLabels; i++) {
_label[i].hidden = YES;
}
CGPoint center = _label[0].center;
center.x = self.center.x - self.frame.origin.x;
_label[0].center = center;
}
}
5.3 當有文字時不能重新布局等操作,因為會抖動
- (void)setText:(NSString *)text{
//如果文字等於當前label的文字,判斷是否大於父視圖寬度,決定是否滾動,可以滾動,設置滾動,並返回
if ([text isEqualToString:_label[0].text]) {
if (_label[0].frame.size.width > self.frame.size.width) {
[self scroll];
}
return;
}
for (NSInteger i = 0; i< NumLabels; i++) {
_label[i].text = text;
}
[self rejustlabels];
}
代碼github地址:https://github.com/TheYouth/STRMarquee
