項目需求中有這么一項,主界面中有用戶狀態(tài)(左上角)以及下面的三個列表,表中的狀態(tài)有解鎖和未解鎖兩種。要求在用戶狀態(tài)發(fā)生改變、大招及場景解鎖后回到主界面出現(xiàn)gif動畫效果。主界面如圖。

最初,通過通知判斷狀態(tài)是否發(fā)生改變,然后出現(xiàn)相應(yīng)的動畫效果。但其他界面發(fā)送解鎖的通知后,會立刻出現(xiàn)動畫效果(動畫加在 window上)。后來使用單例傳值,但其他界面改變解鎖狀態(tài),改變單例類中的相應(yīng)參數(shù),在主界面viewWillAppear中通過判斷程序中的狀態(tài)是否與單例類中的狀態(tài)是否一致,然后是否出現(xiàn)動畫。
狀態(tài)出現(xiàn)是很好判斷的,但在動畫出現(xiàn)遇到了問題。
動畫效果是界面變暗,從原位置出現(xiàn)gif動畫變大,停留3s返回原位置。我使用的是[UIView animated]的block代碼塊完成。在competion中執(zhí)行返回的操作。
[UIView animateWithDuration:1.0f
animations:^{
backView.alpha = ALPHA;
_gifImageView.alpha = 1.0;
_gifImageView.frame = CGRectMake(kWIDTH/2 - gifImage.size.width/2,
kHEIGHT/2 - gifImage.size.height/2,
gifImage.size.width,
gifImage.size.height);
}completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:1.0f animations:^{
[NSThread sleepForTimeInterval:3.0];
backView.alpha = 0;
_gifImageView.alpha = 0;
//恢復(fù)原來的狀態(tài)
_gifImageView.frame = _userStateImage.frame;
}completion:^(BOOL finished) {
[_gifImageView removeFromSuperview];
[backView removeFromSuperview];
}];
}
}];
但是在兩個動畫同時符合要求出現(xiàn)的時候,并沒有按照先后順序出現(xiàn),而是同時出現(xiàn),并且sleep時間出現(xiàn)了疊加。
因此 將[NSThread sleepForTimeInterval:3.0f] 改為[UIView setAnimationDelay:3.0f]延遲3s出現(xiàn)。這樣做雖然解決了時間問題,可是兩個動畫效果同時出現(xiàn) 消失,并沒有出現(xiàn)先后順序。
按照需求的優(yōu)先級,如果兩個效果同時出現(xiàn),要先出現(xiàn)解鎖的效果,然后出現(xiàn)用戶狀態(tài)發(fā)生改變的效果。
方法有更優(yōu)秀的,在這方面我處理的是用了定時器,然后在時間軸上出現(xiàn)效果。
double delayInSeconds = -5.0f;
if ([DCObserveScene defaultObserveScene].actionGroup != nil) {
delayInSeconds += 5.0f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//解鎖大招 通過單例類傳值
[self observerAction:[DCObserveScene defaultObserveScene].actionGroup];
[DCObserveScene defaultObserveScene].actionGroup = nil;
});
}
if (self.oldUserState != self.userStatus) {
delayInSeconds += 5.0f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//對userStatus前后值進行判斷
self.oldUserState = self.userStatus;
[self changeUserStatusAnimation];
});
}
在動畫播放時還有一種是動畫出現(xiàn),然后用戶點擊出現(xiàn)消失動畫。若是一個那很簡單,將消失動畫寫在tapGesture點擊事件中便可以了,可是當(dāng)多個動畫出現(xiàn)時還是會有如上所說的問題。
我設(shè)了一個BOOL類型的變量用來控制是否可以點擊,但執(zhí)行第一個動畫時在點擊事件中判斷第二個是否能夠執(zhí)行,這樣便不會出現(xiàn)同一個方法執(zhí)行兩遍或者多遍的情況。
self.canTap = YES;
//當(dāng)大招解鎖
if ([DCObserveScene defaultObserveScene].actionGroup != nil) {
//解鎖大招 通過單例類傳值
[self observerAction:[DCObserveScene defaultObserveScene].actionGroup];
[DCObserveScene defaultObserveScene].actionGroup = nil;
self.canTap = NO;
}else
//當(dāng)用戶狀態(tài)發(fā)生改變
if (self.oldUserState != self.userStatus) {
//對userStatus前后值進行判斷
self.oldUserState = self.userStatus;
[self changeUserStatusAnimation];
}
changeUserStatusAnimation為動畫出現(xiàn)的方法,在點擊事件中,方法實現(xiàn)如下
- (void)tapGifClick:(UITapGestureRecognizer *)tap{
[UIView animateWithDuration:1.0f animations:^{
_backView.alpha = 0;
_gifImageView.alpha = 0;
//恢復(fù)原來的狀態(tài)
_gifImageView.frame = _userStateImage.frame;
}completion:^(BOOL finished) {
[_gifImageView removeFromSuperview];
[_backView removeFromSuperview];
if(self.canTap == NO&&self.oldUserState != self.userStatus){
self.oldUserState = self.userStatus;
[self changeUserStatusAnimation];
self.canTap = !self.canTap;
}
}];
}
本著能完成需求就是好代碼的原則解決了這個問題,但是并非好的解決方法,希望能和大家多多探討。