iOS - 使用自动布局执行多个同步动画

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS - 使用自动布局执行多个同步动画相关的知识,希望对你有一定的参考价值。

我想要同时执行两个动画动画。 firstView上的第一个动画立即开始。 secondView上的第二个动画,在第一个动画仍在运行时稍有延迟后开始。 secondView约束与firstView有关。该代码在ios 8上运行良好。

firstViewsecondViewview的子视图

view  
    |--- firstView  
    |--- secondView    

码:

UIView *firstView = ...;
UIView *secondView = ...;    

[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
    [self.view addConstraint:constraint];
    [self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];

[UIView animateWithDuration:0.5 delay:0.15 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:secondView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:firstView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
    [self.view addConstraint:constraint];
    [self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];

在iOS 7上,一旦第二个layoutIfNeeded被调用,第一个动画就会停止,只有秒动画会动画化。

有什么建议?

答案

回答我自己的问题。

我最终以2步(3步,取决于你如何计算)解决方案来完成动画。首先添加约束而不调用layoutIfNeeded。然后更新firtViewsecondView帧。最后在最后一个动画的完成块中调用layoutIfNeeded

码:

UIView *firstView = ...;
UIView *secondView = ...;    

/* first step */
NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:firstView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self.view addConstraint:constraint1];
NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:secondView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:firstView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self.view addConstraint:constraint2];

/* second step */
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    CGRect firstViewFrame = CGRectMake(...); // set frame according to constaint1
    firstView.frame = firstViewFrame;
}];

[UIView animateWithDuration:0.5 delay:0.15 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    CGRect secondViewFrame = CGRectMake(...); // set frame according to constaint2
    secondView.frame = secondViewFrame;
} completion:^(BOOL finished) {
    /* second and a half step */
    [self.view setNeedsLayout];
    [self.view layoutIfNeeded];
}];
另一答案

两个重要说明:

  1. 您需要在动画块中调用layoutIfNeeded。 Apple实际上建议您在动画块之前调用一次,以确保所有挂起的布局操作都已完成。
  2. 您需要在父视图(例如self.view)上专门调用它,而不是附加了约束的子视图。这样做会更新所有受约束的视图,包括动画可能被约束到您更改约束的视图的其他视图(例如,视图B附加到视图A的底部,您刚刚更改了视图A的顶部偏移,您希望视图B用它来制作动画)。

你必须这样做:

[self.view layoutIfNeeded];

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self.view addConstraint:constraint];

[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    [self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];

以上是关于iOS - 使用自动布局执行多个同步动画的主要内容,如果未能解决你的问题,请参考以下文章

带有自动布局的新子视图的 iOS 7+ 缩放动画

在 TabLayout 和 ViewPager2 中执行异步任务后更新具有相同布局的多个片段

ios自动布局实现动画

iOS:自动布局:动画后锁定新位置

[iOS]:删除和添加约束时自动布局动画更改框架位置

[OC] autoLayout 博客文档