- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一批动画调用,通过遍历数组调用。所有这些调用都嵌套在一个封装的动画 block 中,以便它们有效地并行执行。我还有一个完成 block ,我只想在所有嵌套动画完成后触发。
问题是嵌套动画的持续时间未知,所以我不能简单地计算哪个调用将是最后一个完成并在此调用上设置完成 block 。同样,我无法计算持续时间并在完成 block 上使用延迟调用。
希望有一个例子可以使这一点更清楚。这是我正在尝试做的(非常简化的)版本:
-(void) animateStuff:(CGFloat)animationDuration withCompletionBlock:(void) (^)(BOOL)completionBlock {
// encapsulating animation block so that all nested animations start at the same time
[UIView animateWithDuration:animationDuration animations:^{
for(MyObject* object in self.array) {
// this method contains other [UIView animateWithDuration calls...
[self animationOfUnknownDurationWithObject:object nestedCompletionBlock:^(BOOL finished) {
// what I effectively what here is:
if(last animation to finish) {
completionBlock(YES);
}
}];
}
}]; // cannot use the completion block for the encapsulating animation block, as it is called straight away
}
使用 dispatch_groups 和异步调用提供的功能如下所述:
http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
显然是理想的,但是 UIView animateWithDuration 调用本身是一个异步调用,因此在 dispatch_group_async 中调用它不会正常工作。
我知道我可以做一些事情,比如让 __block count 变量在 nestedCompletionBlock 中递减,作为确定哪个是最后一个的方法,但在我的代码中,这是非常困惑的(上面是一个简化的例子)。
有什么好的方法吗?也许某种同步执行 animateWithDuration 的方式,以便它可以与 dispatch_group_async 一起工作?
在 iOS 5.0 上工作。
更新:
@Rob-
谢谢你的回答!这几乎解决了我的问题——之前没有研究过 CATransaction,我想我应该在提问之前更深入地研究一下。 :)
但是还有一个问题。正如我之前提到的,我的例子被简化了,剩下的问题是动画有嵌套的完成 block (即,对于链式动画),我需要将其包含在封闭的事务中。
例如,如果我运行以下代码:
-(void) testAnim {
NSArray* testArray = [NSArray arrayWithObjects:self.redView, self.blueView, nil];
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
NSLog(@"All animations complete!");
}];
for(UIView* view in testArray) {
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
NSLog(@"2nd stage complete");
}];
NSLog(@"Animation 2nd stage");
[UIView animateWithDuration:2 animations:^{
setX(view, 100);
}];
} [CATransaction commit];
}];
NSLog(@"animation 1st stage");
[UIView animateWithDuration:2 animations:^{
setX(view, 150);
}];
}[CATransaction commit];
}
} [CATransaction commit];
}
我得到以下输出:
2011-12-08 15:11:35.828 testProj[51550:f803] 动画第一阶段
2011-12-08 15:11:35.831 testProj[51550:f803] 动画第一阶段
2011-12-08 15:11:37.832 testProj[51550:f803] 动画第二阶段
2011-12-08 15:11:37.834 testProj[51550:f803] 动画第二阶段
2011-12-08 15:11:37.848 testProj[51550:f803] 所有动画完成!
2011-12-08 15:11:39.834 testProj[51550:f803] 第二阶段完成
2011-12-08 15:11:39.851 testProj[51550:f803] 第二阶段完成
而我需要的是“所有动画完成!”只有在所有内部操作结束后才会触发事件。
也许是因为我只在类级别设置完成 block ,因此无法将每个 block 绑定(bind)到特定操作?
无论如何我还是不太明白,使用 UIView animateWithDuration 重载和它自己的完成 block 参数只会引发同样的问题。
有什么想法吗?
最佳答案
将整个事情包装在 CATransaction
中,并设置事务的 completionBlock
。这是我的测试:
static void setX(UIView *view, CGFloat x)
{
CGRect frame = view.frame;
frame.origin.x = x;
view.frame = frame;
}
- (IBAction)startAnimation:(id)sender {
label.text = @"Animation starting!";
setX(redView, 0);
setX(blueView, 0);
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
label.text = @"Animation complete!";
}];
[UIView animateWithDuration:1 animations:^{
setX(redView, 300);
}];
[UIView animateWithDuration:2 animations:^{
setX(blueView, 300);
}];
} [CATransaction commit];
}
如果您还没有添加 QuartzCore 框架,则需要添加。
关于您更新后的问题:由于您是从完成 block 创建新动画,这些新动画不会成为原始交易的一部分,因此原始交易不会等待它们完成。
通过使用 +[UIView animateWithDuration:delay:options:animations:completion:]
以及启动稍后在适当的时间播放动画。
关于iphone - 如何为一组嵌套的 UIView animateWithDuration 调用调用单个完成 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8421441/
我正在使用这些(代码块 1 和 2)将带有动画的 UIScrollView 从开始移动到我的结束点(x:0 到 1000,在这个例子中) 代码块 1: UIScrollView.animateWith
-(void)fadeLabel{ UILabel *label = (UILabel *)[self.view viewWithTag:kLabelTag]; [UIView ani
我正在使用 animateWithDuration 让我的 UIVIew 之一无休止地旋转。现在,我需要获取 UIView 在特定时间旋转的当前值。我尝试使用以下功能: -(float)getCurr
我在 viewController 中有一个循环动画 - (void)moveAnimating { [UIView animateWithDuration:2.0f animations:^
出于某种原因,如果我只使用代码: [UIView animateWithDuration:.5 delay:0 options:UIViewAn
我正在学习 Swift,但在从不同函数移动 UIView 时遇到问题。如果我使用这个: View Controller : let boardView = BoardView() @IBAction
let downFrame = CGRect(x: 0, y: ScreenSize.height, width: ScreenSize.width, height: ScreenSize.heigh
我试图让“luke”跳过一个物体以确保游戏不会结束,他确实这样做了,但即使他避开了物体,游戏仍然会结束,就好像 luke 在游戏过程中没有离开他原来的位置一样动画。 我在 -(void)touches
我在 UIViewController 中使用此方法来显示一条消息三秒钟,然后淡出。 mainMessageLabel 是在接口(interface)文件中声明的 UILabel。 - (void)
我正在尝试对三个 UILabel(display1、display2、display3)进行交叉溶解,方法是使用 block 动画淡出、更改文本,然后一次淡入一个。我使用的代码是: [UIView a
今天 animateWithDuration 表现得很愚蠢,我不知道为什么。我检查了所有的东西,所有的括号,一切都很完美,但它总是呈现我没有指定为动画的代码行。 好的,这就是重点。我有一个 longP
我有一个没有自动布局的 ViewController,我正在尝试为一些按钮设置动画。我在 ViewDidAppear 中有一些 UIView animateWithDuration 代码,那里的一切都
我想在我的标签上先淡出然后淡入,我可以让两者分开工作但不能一起工作。 [UILabel animateWithDuration:1.0 animations:^{ _swixV
我正在尝试运行示例来测试此功能。我在 Storyboard中有一个标签和一个按钮,我在 View Controller 中引用了标签的底部约束。当我使用按钮时,我希望标签随动画一起移动,但它在没有动画
我有一个用 animateWithDuration 和 setAnimationRepeatCount() 动画的脉冲矩形。 我正在尝试在同步“点击”的动画 block 中添加声音效果。但音效只播放一
我在 switch 语句中有一段动画,该语句运行并执行预期的操作。在计时器内每二十秒成功调用一次动画。但是,动画不会在任何时候发生,而是在第一次发生。在我下面的代码中,您将看到我用来尝试突出显示问题的
我正在尝试将 JSSAlertView ( github.com/stakes/JSSAlertView ) 与 Swift 2.0 一起使用,但出现错误: Cannot invoke animate
我在我的 ScrollView 委托(delegate)方法 scrollViewDidEndDragging 中执行了一个简单的动画。 看起来像这样: - (void)scrollViewDidEn
我有一个 CollectionView,我想在用户选择的 CollectionViewCell 中创建一个动画。我选择使用 animateKeyframesWithDuration 是因为我想逐步创建
在执行 UIView.animateWithDuration 时,我想定义一条自定义曲线以方便使用,而不是默认曲线:.CurveEaseInOut、.CurveEaseIn、.CurveEaseOut
我是一名优秀的程序员,十分优秀!