在 iOS 10 中处理 AutoLayout 约束动画差异?

Handling AutoLayout constraint animation differences in iOS 10?

我注意到在 iOS 10 Beta 5(即将尝试 Beta 6)中,AutoLayout 约束动画的行为有点不同。

例如,此方法的工作方式与以前的 iOS 版本不同:

[view addConstraints:@[constraints...]];

[view setNeedsUpdateConstraints];
[view layoutIfNeeded];

[UIView animateWithDuration:...
{
    /* adjust constraint here... */
    [view layoutIfNeeded]; // Only the adjusted constraints since previous layoutIfNeeded() call should animate change with duration.

} completion:{ ... }];

... 在我的测试中,最初使用 addConstraints() 添加的约束将 也会 在 iOS 10 中使用 UIView animateWithDuration() 进行动画处理阻止...到目前为止,这导致了一些 funky/undesirable 行为。

例如,在数组中设置 left/right 约束(但在块中设置垂直约束)导致整个视图以对角线 动画显示在屏幕上方法...完全不正确。

有谁知道如何为 iOS 9(及以下)以及 10 正确执行此操作?

我做了一个小测试,改变小红视图的 H 和 V:

self.red_POS_H = NSLayoutConstraint.constraints(withVisualFormat: "H:|-90-[redView]", options: defaultOptions, metrics: nil, views: viewsDictionary)


self.red_POS_V = NSLayoutConstraint.constraints(withVisualFormat: "V:|-30-[redView]", options: defaultOptions, metrics: nil, views: viewsDictionary)

self.view.addConstraints(self.red_POS_V!)
self.view.addConstraints(self.red_POS_H!)

并为其制作动画:

        // we hope is only one:
        let currV = self.red_POS_V![0]
        let currH = self.red_POS_H![0]


        UIView.animate(withDuration: 3) { 
            // Make all constraint changes here

            currV.constant = 100
            currH.constant = 300

            self.view.layoutIfNeeded() // Forces the layout of the subtree animation block and then captures all of the frame changes
        }

红色视图正确移动,如果您在动画中注释掉单行,它在水平或垂直方向上都有效。

小项目可用,如果你需要的话。

尝试在视图的父视图上调用 layoutIfNeeded,而不是视图本身。

--

我有一个类似的问题,我的视图应该从顶部的 0 高度开始动画,向下到 > 0 高度(即 (0, 0, 320, 0) 到 (0, 0, 320, 44)).

使用 Xcode 8 和 iOS 10,动画行为有很大不同。视图不是从顶部向下动画,而是从目标框架的垂直中心向上和向下动画。

我修复了这个问题,而不是在视图本身上调用 layoutIfNeeded,而是在视图的父视图上调用它。不知何故,行为恢复了。

希望对您有所帮助!


@Ramiro 的有用评论:

According to the documentation, layoutIfNeeded lays out the subviews (but doesn't contemplate the current view itself). So, in order to update the current view lay out, you need to call layoutIfNeeded from the super view.

在下面的方法中:

[super viewDidLoad];

写下这一行:

 [self.view layoutIfNeeded];