【问题标题】:UIView animations interacting badlyUIView 动画交互不好
【发布时间】:2009-05-08 23:54:51
【问题描述】:

我看到了似乎是单独动画之间的交互,我非常感谢任何消除这种影响的建议。

基本上: 我有一个 iPhone 应用程序,它在根视图上包含一个按钮“a”。点击“a”将视图推送到导航视图控制器堆栈上,并带有翻转动画。推送的视图有一个按钮可以将视图弹出回根目录。

底层代码:

- (IBAction)pushOneView{
TheAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight 
                    forView:delegate.navigationController.view cache:NO];
[delegate.navigationController 
            pushViewController:oneViewController animated:NO];
[UIView commitAnimations];

}

这似乎工作正常,动画也很流畅。

根视图还包括一个子视图(“panelView”)和另一个按钮“b”。 panelView 可以显示其他两个子视图中的任何一个——在这些子视图之间点击“b”交换,并带有旋转动画。代码:

-(IBAction)swapPanels{
UIViewController *coming;
UIViewController *going;
float rotation;

if (self.aPanel.view.superview == nil) {
    coming = aPanel;
    going = bPanel;
    rotation = 3.14;
}
else {
    coming = bPanel;
    going = aPanel;
    rotation = -3.14;
}

// First half of spin
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
CGAffineTransform swirlTransform = CGAffineTransformMakeRotation(rotation);
panelView.transform = swirlTransform;
[panelView setAlpha:0.1];
[UIView commitAnimations];

// Finish spin
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
CGAffineTransform secondTransform = 
                        CGAffineTransformRotate(swirlTransform, rotation);
panelView.transform = secondTransform;
[panelView setAlpha:1];
[UIView commitAnimations];

// Swap the panels
[going.view removeFromSuperview];
[panelView insertSubview:coming.view atIndex:0];

}

这似乎也可以正常工作。每个可交换面板都包含一个选择器和一些标签。

但是,我注意到如果在“b”转换之前执行过“a”转换,它会变得缓慢且不稳定。 换句话说,如果我启动应用程序,来回运行“a”几次,它运行顺利。然后来回练习'b'几次。然后再次尝试“a”...“a”现在很不稳定,并且会一直保持这种状态,直到应用重新启动。

这是 100% 可重复的。使用模拟器很微妙,但在设备上却很明显。 我已经测试过泄漏——泄漏工具没有显示任何泄漏。 如果动画从 'b' 操作中移除(只是注释掉动画步骤),则在执行 'b' 子视图交换后不会观察到对 'a' 的影响。 如果将拾取器从可更换的面板笔尖中移除,则类似地消除了该效果。 如果“a”动画过渡设置为缓存,那么在“b”之后它不会在中间卡顿,而是似乎忽略动画,只是交换视图(这可能是感知问题)。

如果我不清楚:我不会同时触发这些单独的操作。动画 'a',在 'b' 被执行之后——并且完成——与 'b' 从未被执行是不一样的。动画后我应该做清理工作吗?我的子视图交换代码有缺陷吗?还是……?

提前感谢您的任何建议。

【问题讨论】:

    标签: iphone animation uiview


    【解决方案1】:

    您的“b”部分确实有两个重叠的动画。当您使用开始/提交块创建动画时,它会被移交给后台线程来执行。在您的“b”部分中,应该连续的两个动画实际上几乎同时被触发。这可能会导致奇怪的行为,可能就像您所看到的那样。

    我建议使用如下代码在您的第一个动画中将回调添加到委托方法:

    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(rotationAnimationFinished:finished:context:)];
    

    在“b”中的第一个动画块内(“旋转的前半部分”部分)。然后你需要在你的类中定义回调方法,在这种情况下

    - (void)rotationAnimationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context;
    

    在该委托方法中,将在旋转动画的第一部分完成时调用,放置您的“b”方法中的剩余代码(“完成旋转”注释之后的所有内容)。

    通过将这些动画分开,这可能会防止您看到的怪异现象。

    【讨论】:

    • 非常感谢布拉德的建议,但我认为我们还没有到那里。虽然我理解您的观点,但对其的一项测试是完全消除“b”动画的后半部分……这样做对“a”动画的行为没有影响。
    【解决方案2】:

    Brad 的回答确实 似乎让我找到了解决方案:症状继续表明运行那些“b”动画的某些原因使系统处于与启动时不同的状态。最后,我想到 panelView 的 transform 属性是在 'b' 动画之后设置的……这可能会影响包含 panelView 的 superview 的进一步动画。

    所以我按照 Brad 的建议设置了方法,在“b”动画完成后执行——但该方法所做的只是将 panelView 转换设置回默认值:CGAffineTransformIdentity:

    • (void)spinFinished:(NSString *)animationID 完成:(BOOL)完成上下文:(void *)context { panelView.transform = CGAffineTransformIdentity; }

    有了这个,“a”动画的“b”后执行似乎恢复了正常。再次感谢布拉德,感谢您在这里的帮助。 非常感激。

    【讨论】:

    • 为什么不选择布拉德的答案作为解决方案?