技術(shù)感(Che)悟(Dan)(可跳過(guò))
遇到某技術(shù)問(wèn)題時(shí)斤寇,第一眼看起來(lái)實(shí)現(xiàn)特別復(fù)雜,但又沒(méi)有更好的思路乐横,只有硬著頭皮做下去求橄。耗費(fèi)了巨大的時(shí)間和精力,最終完成晰奖,成就感爆棚的同時(shí)卻總感覺(jué)不夠優(yōu)雅谈撒。無(wú)奈開(kāi)發(fā)任務(wù)緊迫腥泥,只好擱置匾南。待到閑暇時(shí)光(不存在的,嘮嗑蛔外、斗圖都是正經(jīng)事好不好??)蛆楞,細(xì)思起來(lái)不是實(shí)現(xiàn)復(fù)雜,而是思路偏了夹厌,找到最優(yōu)解豹爹,才是我輩進(jìn)取(裝逼)之路矛纹。
俗話說(shuō):不折騰開(kāi)發(fā)的二貨不是好產(chǎn)品臂聋,設(shè)計(jì)之初是用個(gè)短視頻作為背景,話不多說(shuō),BackgroundVideoiOS 搬磚完畢孩等。然而事情怎會(huì)如此順利艾君,運(yùn)營(yíng)給出視頻太大,壓縮后又模糊不清肄方,此方案只好作罷冰垄。
那就用圖片自己做唄,畢竟有多年Banner經(jīng)驗(yàn)权她,此事應(yīng)該不難虹茶,然而真是這樣?圖片輪播展示完畢的切換卡頓隅要,哪可能逃過(guò)產(chǎn)品Dog(就說(shuō)了能咋地蝴罪?)的法眼。下面才是入坑的開(kāi)始:思路是兩張一樣的圖片并排排列步清,首尾相連洲炊,同時(shí)左移,設(shè)置相同動(dòng)畫(huà)時(shí)間尼啡,X值不斷減小暂衡,動(dòng)畫(huà)結(jié)束回調(diào)Frame重置方法,遞歸回調(diào)
#import <UIKit/UIKit.h>
typedef void(^MoveAnimationBlock)(void);
@interface MoveAnimationView : UIView
/**
向左移動(dòng)
@param view 視圖
@param timer 時(shí)間
@param block 回調(diào)方法
*/
+ (void)leftTranslationAnimationView:(UIView *)view
animationDuration:(NSTimeInterval)timer
animationBlock:(MoveAnimationBlock)block;
@end
#import "MoveAnimationView.h"
@implementation MoveAnimationView
+ (void)leftTranslationAnimationView:(UIView *)view animationDuration:(NSTimeInterval)timer animationBlock:(MoveAnimationBlock)block {
[UIView animateWithDuration:timer delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
CGRect frame = view.frame;
frame.origin.x = frame.origin.x - frame.size.width;
view.frame = frame;
} completion:^(BOOL finished) {
if (finished) {
block();
}
}];
}
@end
為了解決崖瞭,跳出當(dāng)前頁(yè)面返回后動(dòng)畫(huà)停止的問(wèn)題狂巢,需在viewWillAppear方法中調(diào)用:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self startMoveAnimation];
}
- (void)startMoveAnimation {
UIImage *bgImg = [UIImage imageNamed:@"first_login_bg.jpg"];
CGFloat width = 1.f * bgImg.size.width / bgImg.size.height * kScreenHeight;
self.bgImgV_1.frame = CGRectMake(0, 0, width, kScreenHeight);
self.bgImgV_2.frame = CGRectMake(width, 0, width, kScreenHeight);
[self moveBgImgV_1Animation];
[self moveBgImgV_2Animation];
}
- (UIImageView *)bgImgV_1 {
if (!_bgImgV_1) {
_bgImgV_1 = [[UIImageView alloc]initWithFrame:CGRectZero];
_bgImgV_1.image = [UIImage imageNamed:@"first_login_bg.jpg"];
}
return _bgImgV_1;
}
- (UIImageView *)bgImgV_2 {
if (!_bgImgV_2) {
_bgImgV_2 = [[UIImageView alloc]initWithFrame:CGRectZero];
_bgImgV_2.image = [UIImage imageNamed:@"first_login_bg.jpg"];
}
return _bgImgV_2;
}
- (void)moveBgImgV_1Animation
{
WeakSelf
[MoveAnimationView leftTranslationAnimationView:self.bgImgV_1 animationDuration:36 animationBlock:^{
CGRect frame = _self.bgImgV_1.frame;
frame.origin.x =_self.bgImgV_1.width;
//右移動(dòng)
//frame.origin.x = 0;
_self.bgImgV_1.frame = frame;
[_self moveBgImgV_1Animation];
}];
}
- (void)moveBgImgV_2Animation
{
WeakSelf
[MoveAnimationView leftTranslationAnimationView:self.bgImgV_2 animationDuration:36 animationBlock:^{
CGRect frame = _self.bgImgV_2.frame;
frame.origin.x = 0;
//右移動(dòng)
//frame.origin.x = -_self.bgImgV_2.width;
_self.bgImgV_2.frame = frame;
[_self moveBgImgV_2Animation];
}];
}
貌似完美解決,可以交工喝茶了书聚,然而如最初所言唧领,總是感覺(jué)不夠優(yōu)雅,還有跳出再返回此頁(yè)面動(dòng)畫(huà)總是重頭開(kāi)始雌续。
下面敲黑板斩个,重點(diǎn)來(lái)了,如何用核心動(dòng)畫(huà)打開(kāi)尷尬局面驯杜,說(shuō)干就干:
- (void)startMoveAnimation {
UIImage *bgImg = [UIImage imageNamed:@"first_login_bg.jpg"];
CGFloat width = 1.f * bgImg.size.width / bgImg.size.height * kScreenHeight;
UIImageView *bgImgV_1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, width, kScreenHeight)];
bgImgV_1.image = bgImg;
UIImageView *bgImgV_2 = [[UIImageView alloc] initWithFrame:CGRectMake(width, 0, width, kScreenHeight)];
bgImgV_2.image = [UIImage imageNamed:@"first_login_bg.jpg"];
[self.view addSubview:bgImgV_2];
[self.view addSubview:bgImgV_1];
CFTimeInterval duration = 36;
CABasicAnimation *anim1 = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
anim1.toValue = @(-width);
anim1.duration = duration;
anim1.repeatCount = HUGE_VALF;
anim1.removedOnCompletion = NO; //解決頁(yè)面切換之后受啥,動(dòng)畫(huà)久停止的問(wèn)題,其實(shí)是
[bgImgV_1.layer addAnimation:anim1 forKey:nil];
CABasicAnimation *anim2 = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
anim2.toValue = @(-width);
anim2.duration = duration;
anim2.repeatCount = HUGE_VALF;
anim2.removedOnCompletion = NO;
[bgImgV_2.layer addAnimation:anim2 forKey:nil];
}
CABasicAnimation使用總結(jié)
解釋:為什么動(dòng)畫(huà)結(jié)束后返回原狀態(tài)鸽心?
首先我們需要搞明白一點(diǎn)的是滚局,layer動(dòng)畫(huà)運(yùn)行的過(guò)程是怎樣的?其實(shí)在我們給一個(gè)視圖添加layer動(dòng)畫(huà)時(shí)顽频,真正移動(dòng)并不是我們的視圖本身藤肢,而是 presentation layer 的一個(gè)緩存。動(dòng)畫(huà)開(kāi)始時(shí) presentation layer開(kāi)始移動(dòng)糯景,原始layer隱藏嘁圈,動(dòng)畫(huà)結(jié)束時(shí)省骂,presentation layer從屏幕上移除,原始layer顯示最住。這就解釋了為什么我們的視圖在動(dòng)畫(huà)結(jié)束后又回到了原來(lái)的狀態(tài)冀宴,因?yàn)樗揪蜎](méi)動(dòng)過(guò)。
這個(gè)同樣也可以解釋為什么在動(dòng)畫(huà)移動(dòng)過(guò)程中温学,我們?yōu)楹尾荒軐?duì)其進(jìn)行任何操作略贮。
所以在我們完成layer動(dòng)畫(huà)之后,最好將我們的layer屬性設(shè)置為我們最終狀態(tài)的屬性仗岖,然后將presentation layer 移除掉逃延。
至此效果上看來(lái)是夠優(yōu)雅了,代碼不優(yōu)雅的地方歡迎指正轧拄!