void (^first_animation)();
void (^second_animation)(BOOL finished);
// First animation
first_animation = ^()
{
g_pin_info_screen.view.alpha = 1.0;
};
// Second animation
second_animation = ^(BOOL finished)
{
g_shadow_layer.opacity = 0.0;
void (^set_opacity_to_1)();
set_opacity_to_1 = ^()
{
g_shadow_layer.opacity = 1.0;
};
[UIView animateWithDuration : 2.0
delay : 0.0
options : UIViewAnimationCurveEaseInOut
animations : set_opacity_to_1
completion : nil
];
};
// Begin the animations
{
float duration;
duration = 0.35;
[UIView animateWithDuration : duration
delay : 0.00
options : UIViewAnimationCurveEaseInOut
animations : first_animation
completion : second_animation
];
}
第一个动画按预期执行。但第二个动画完成但没有任何动画。
希望有人能评论上述方案是否是这样做的正确方法。
答案 0 :(得分:12)
__block NSMutableArray* animationBlocks = [NSMutableArray new];
typedef void(^animationBlock)(BOOL);
// getNextAnimation
// removes the first block in the queue and returns it
animationBlock (^getNextAnimation)() = ^{
if ([animationBlocks count] > 0){
animationBlock block = (animationBlock)[animationBlocks objectAtIndex:0];
[animationBlocks removeObjectAtIndex:0];
return block;
} else {
return ^(BOOL finished){
animationBlocks = nil;
};
}
};
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//my first set of animations
} completion: getNextAnimation()];
}];
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//second set of animations
} completion: getNextAnimation()];
}];
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//third set
} completion: getNextAnimation()];
}];
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//last set of animations
} completion:getNextAnimation()];
}];
// execute the first block in the queue
getNextAnimation()(YES);
答案 1 :(得分:2)
在第三方库的帮助下,有一个如下所示的解决方案:
首先,为方便起见,为UIView
定义一个类别:
+(RXPromise*) rx_animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations
{
RXPromise* promise = [RXPromise new];
[UIView animateWithDuration:duration animations:animations: ^(BOOL finished){
// ignore param finished here
[promise fulfillWithValue:@"finished"]; // return just a string indicating success
}];
return promise;
}
然后,定义一个接一个地执行的任意数量的异步动画,如下所示:
[UIView rx_animateWithDuration:duration animation:^{
... //define first animation
}]
.then(^id(id result){
// ignore result, it contains the fulfill value of the promise, which is @"finished"
return [UIView rx_animateWithDuration:duration animation:^{
... // define second animation
}];
}, nil)
.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // define third animation
}];
}, nil)
.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // and so force
};
}, nil);
以上陈述是异步的!
使用一行附加代码,您可以取消:
RXPromise* rootPromise = [UIView rx_animateWithDuration:duration animation:^{
... //define first animation
}];
rootPromise.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // define second animation
}];
}, nil)
.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // define third animation
}];
}, nil)
...
// later, in case you need to cancel pending animations:
[rootPromise cancel];
“RXPromise”库可在GitHub上找到:RXPromise。它专为这些用例而设计,等等。由于完全披露:我是作者;)
答案 2 :(得分:1)
请点击此处: https://gist.github.com/vadimsmirnovnsk/bce345ab81a1cea25a38
您可以将其链接为功能样式:
dispatch_block_t animationsBlock = ^{
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
};
[[[[[[[[[BARAnimation construct]
initially:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(32.0);
}];
} animations:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(0.0);
}];
} animations:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(-32.0);
}];
} animations:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(0.0);
}];
} animations:animationsBlock]
animationWithDuration:0.8 animationConditions:nil animations:^{
foreView.alpha = 1.0;
}]
finally:^{
[self.didEndSubject sendNext:[RACUnit defaultUnit]];
[self.didEndSubject sendCompleted];
}]
run];
答案 3 :(得分:0)
您需要使用+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
在options:
参数中,您需要包含UIViewAnimationOptionBeginFromCurrentState
答案 4 :(得分:0)
在第一个动画的完成处理程序中,启动第二个动画。