项目需求中有这么一项,主界面中有用户状态(左上角)以及下面的三个列表,表中的状态有解锁和未解锁两种。要求在用户状态发生改变、大招及场景解锁后回到主界面出现gif动画效果。主界面如图。
主界面
最初,通过通知判断状态是否发生改变,然后出现相应的动画效果。但其他界面发送解锁的通知后,会立刻出现动画效果(动画加在 window
上)。后来使用单例传值,但其他界面改变解锁状态,改变单例类中的相应参数,在主界面viewWillAppear
中通过判断程序中的状态是否与单例类中的状态是否一致,然后是否出现动画。
状态出现是很好判断的,但在动画出现遇到了问题。
动画效果是界面变暗,从原位置出现gif动画变大,停留3s返回原位置。我使用的是[UIView animated]
的block
代码块完成。在competion
中执行返回的操作。
[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;
//恢复原来的状态
_gifImageView.frame = _userStateImage.frame;
}completion:^(BOOL finished) {
[_gifImageView removeFromSuperview];
[backView removeFromSuperview];
}];
}
}];
但是在两个动画同时符合要求出现的时候,并没有按照先后顺序出现,而是同时出现,并且sleep
时间出现了叠加。
因此 将[NSThread sleepForTimeInterval:3.0f]
改为[UIView setAnimationDelay:3.0f]
延迟3s出现。这样做虽然解决了时间问题,可是两个动画效果同时出现 消失,并没有出现先后顺序。
按照需求的优先级,如果两个效果同时出现,要先出现解锁的效果,然后出现用户状态发生改变的效果。
方法有更优秀的,在这方面我处理的是用了定时器,然后在时间轴上出现效果。
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];
});
}
在动画播放时还有一种是动画出现,然后用户点击出现消失动画。若是一个那很简单,将消失动画写在tapGesture点击事件中便可以了,可是当多个动画出现时还是会有如上所说的问题。
我设了一个BOOL类型的变量用来控制是否可以点击,但执行第一个动画时在点击事件中判断第二个是否能够执行,这样便不会出现同一个方法执行两遍或者多遍的情况。
self.canTap = YES;
//当大招解锁
if ([DCObserveScene defaultObserveScene].actionGroup != nil) {
//解锁大招 通过单例类传值
[self observerAction:[DCObserveScene defaultObserveScene].actionGroup];
[DCObserveScene defaultObserveScene].actionGroup = nil;
self.canTap = NO;
}else
//当用户状态发生改变
if (self.oldUserState != self.userStatus) {
//对userStatus前后值进行判断
self.oldUserState = self.userStatus;
[self changeUserStatusAnimation];
}
changeUserStatusAnimation
为动画出现的方法,在点击事件中,方法实现如下
- (void)tapGifClick:(UITapGestureRecognizer *)tap{
[UIView animateWithDuration:1.0f animations:^{
_backView.alpha = 0;
_gifImageView.alpha = 0;
//恢复原来的状态
_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;
}
}];
}
本着能完成需求就是好代码的原则解决了这个问题,但是并非好的解决方法,希望能和大家多多探讨。
网友评论