【问题标题】:how to animate views change views hierarchy using autolayout?如何使用自动布局动画视图更改视图层次结构?
【发布时间】:2023-04-03 01:43:01
【问题描述】:

我有一个名为 self.myMainView 的超级视图

在那个视图中,我有三个子视图:UIView *view1(绿色视图)、UIView *view2(灰色视图)、UIImageView *view3

我想动画视图 3 的移动

当视图 3 完成后,我想要更改视图层次结构,例如屏幕截图。

这里是示例图片:

【问题讨论】:

  • @matt 这个图像视图例如,这有什么价值?视图 3 的行为可能不正确?
  • 以便我可以尝试重现该问题。正在努力...
  • 嘿,马特,如果你能帮助我,我可以为你制作一个包含所有有价值代码的模型,你需要这个吗?
  • 不,我已经重现了这个问题!你的描述很好。现在我正在寻找解决方案...
  • 我想通了!这是因为您在情节提要中启用了自动布局

标签: ios animation view subview


【解决方案1】:

您正在做的是更改视图分层顺序的正常标准方法。所以问题不在于这个,而用你的话来说“但是,它违反了我的动画”和“粉碎我的动画”。那么,问题在于你的动画,如果它可以通过重新排列图层来“违反”和“粉碎”。但是,在您的问题中,您没有提供有关动画的任何信息!然而,这显然是问题的核心。

编辑:既然您已经发布了动画代码,我就可以进行测试了,我明白了问题所在。问题是您使用的是自动布局。

view3 由约束定位。当您为view3 的位置设置动画时,您违反了这些约束,但这不会立即变得明显。但是当你交换view1view2的分层顺序时,就会进行布局!然后强制执行view3 上的约束。由于这些限制没有改变,我们看到 view3 回到原来的位置。

最简单的解决方案是在不需要时关闭自动布局。否则,您将不得不在动画之后或作为动画的一部分更改约束。事实上,您可以通过动画其位置约束来重新定位view3。我在我的书中描述了这一切,在这里:http://www.apeth.com/iOSBook/ch17.html#_animation_and_autolayout

【讨论】:

  • 谢谢!)昨天我读了你书中关于观点的一章:)谢谢你的工作,你做得很好!
  • 希望本书的这一部分对你有所帮助。它以与您的示例非常相似的示例开始,其中视图“跳回”到它开始的位置。然后我给出了各种解决方案。
  • 你好,马特,我想问你关于你书中代码中的一个问题,我使用的代码是动画定位视图的约束的变化,这里的代码有这个问题并抛出异常:Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 128552240 beyond bounds [0 .. 17]' 代码是:NSUInteger indexOfconstraintsAttribute = [constraintsForAnimation indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){...} xcode 担心类型 NSUInteger 一定是 NSIndexSet 为什么?
  • 我在之前的评论中犯了一个错误,在我的代码中,我将indexesOfObjectsPassingTest: 更改为indexOfObjectPassingTest:,但Xcode 仍然抛出异常。同样的错误:2013-04-25 18:05:31.948 MyFirstApp[8676:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 2147483647 beyond bounds [0 .. 18]'我不知道出了什么问题
  • cmets 不是第二个问题的好地方;相反,只需提出一个新问题!这样您就可以正确显示您的代码等。
【解决方案2】:

如果您只想切换 2 个子视图中的哪一个在另一个之上,您可以简单地使用 [UIView bringSubviewToFront:] 而不是直接弄乱您的子视图数组的顺序吗?这可能会解决动画问题。我会尝试的另一件事是在您对exchangeSubviewAtIndex 的调用周围加上if( finished ),以确保它不会干扰其他动画视图。

【讨论】:

  • bringSubviewToFront 不适合我的目的,我已经尝试过了,但我现在会尝试if(finished)
  • 嗯好吧,我会四处寻找,看看能不能找到解决办法。
  • 没问题!很高兴你把它整理好了。
【解决方案3】:

问题在于视图 3 的约束在动画后不会改变,当我们想要操纵视图层次结构时,动画会停止正常工作。马特在他的回答中谈到了这一点,他还从他的好书中提供了一个解决方案:http://www.apeth.com/iOSBook/ch17.html#_animation_and_autolayout 谢谢你的那个马特。

我稍微更改了此解决方案,并决定将其发布在此处以供需要此解决方案的任何人使用。但如果你想更好地理解这一点,我强烈建议你阅读书中关于动画的章节,链接在上面。

首先,我们需要为视图 3 的移动设置动画,然后更改我们的约束,并且只有在此之后才更改视图层次结构。在书中找到了几种方法来做到这一点,但在我看来这是最好的:

layout = -35.0; //  new constraint constant of self.view3

NSArray *constraintsForAnimation = self.myMainView.constraints; // all constraints of superview 

NSUInteger indexOfconstraintsAttribute = [constraintsForAnimation
indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){ // get index of constraint of view 3

    NSLayoutConstraint *constraint = obj;


    return (([constraint.firstItem isEqual: self.view3])) ? idx : NO; // return this index if we found constraint of view 3

}];


constraint.constant = layout; // changing the constraint of view3 

[UIView animateWithDuration:0.3 animations:^{ // animation
   [self.view3 layoutIfNeeded]; // apply new constraints to view3
}];


[self.myMainView exchangeSubviewAtIndex:3 withSubviewAtIndex:4];// toggle view 1 with view 2

我们仅在约束的帮助下移动视图 3,我们不设置框架或中心视图属性。 好的,我们完成了,这就像我想要的那样工作。希望这对您也有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多