以编程方式修改自动布局约束时视图不更新
Posted
技术标签:
【中文标题】以编程方式修改自动布局约束时视图不更新【英文标题】:View not updating when autolayout constraint modified programmatically 【发布时间】:2014-05-30 20:29:48 【问题描述】:在修改第二个约束(第一个工作正常)后,我无法让我的视图正确布局。我正在修改一个约束,对其进行动画处理,然后在完成块中修改另一个约束(没有动画)。
我这样做的原因是我不希望第二个约束更改影响动画,但我希望它在初始动画完成后立即生效。
问题是第二个约束更改根本没有生效,无论我尝试什么。
这是我正在尝试的(请注意,问题仅在 toolbarVisible
为 YES
时,因为当它为 NO
时我会预先执行两个动画):
if ( !toolbarVisible )
self.containerViewBottomSpace.constant = toolbarVisible ? 60.f : 0;
self.toolbarBottomSpace.constant = toolbarVisible ? 0 : 60.f; // this one works fine
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:0.3f animations:^
[self.view layoutIfNeeded];
completion:^(BOOL finished)
if ( toolbarVisible )
self.containerViewBottomSpace.constant = 60.f; // this one is not taking effect
[self.view setNeedsUpdateConstraints];
[self.view layoutIfNeeded];
];
上述方法发生在observeValueForKeyPath:...
方法中。我尝试将上面的整个代码包装在 dispatch_after
块中,但这会产生更糟糕的效果,因为它总是落后一步(即 containerView 总是处于应有的相反位置),就好像第二个约束一样在下一个动画之前,修改不会生效。
同样,如果我将另一个视图推送到导航控制器(嵌入在 containerView 中),布局会自行纠正。就好像它只是无视我的命令,出于某种原因重新布置。
实际上,我只是注意到,即使我最初进行了第二次更改并完全跳过了完成块,它似乎并没有在所有情况下为第二次约束更改设置动画。有点可疑。
更新:我使用 dispatch_after
错误地认为它接受了 NSTimeInterval。在给它一个适当的dispatch_time_t
并将其放入完成块之后,布局现在有时会更新。但是,它非常不稳定,而且看起来很hackish,所以我觉得好像我错过了一些东西。如果有人对此了解更多,请赐教,我会给你答案。
更新 2: 我决定尝试在 viewDidLayoutSubviews
中记录我要更改的元素的高度。有趣的是,它被调用了两次,第一次使用之前的值,第二次使用正确调整的高度。所以我猜它至少 部分 正确地布置了东西,但由于某种原因,containerView 内部的 tableView 仍然没有正确调整自己的大小。我不确定我错过了什么。
【问题讨论】:
【参考方案1】:我会先设置断点,并确保在动画持续时间内您没有第二次点击动画代码。如果它在 observeValueForKeyPath 中,您可能会多次点击动画,这会导致一些不一致。
您也不需要调用 setNeedsUpdateConstraints 或 layoutIfNeeded。设置常量就足够了。
我还要确保您已正确连接约束并且 toolbarVisible 为 true。
【讨论】:
我正在记录一些调试语句,以确保它只在预期的时候被调用一次。约束是正确连接的,因为更改最终会生效,而不是在应该的时候立即生效。例如,如果我旋转设备,它会突然正确渲染,包括我是否旋转回原始方向。以上是关于以编程方式修改自动布局约束时视图不更新的主要内容,如果未能解决你的问题,请参考以下文章
自定义 tableviewcell 动态高度未根据约束更新(以编程方式自动布局)