通过动画调整 UIView 大小时约束不起作用
Posted
技术标签:
【中文标题】通过动画调整 UIView 大小时约束不起作用【英文标题】:Constraints not working when Resizing UIView via Animation 【发布时间】:2014-02-19 06:01:53 【问题描述】:我现在面临的很奇怪,我知道在 AutoLayout IB 中添加约束很简单。但是当我调整(ZoomIn 动画)UIView 的大小时,我真的无法弄清楚为什么我的简单约束不起作用。
我定位到 zoomIn 的视图工作正常,但其中的子视图定位不正确。约束似乎不起作用。
在此设置中,黄色框是 UIView,绿色框是 UIImageView。 当我点击黄色框时,它应该放大,如下图所示。
这些是约束:
这应该是 zoomIn 动画的预期结果但是我没有运气,黄色框 zoomIn 但绿色框被放置在其旧位置并且没有改变大小。
我已经将 Yellow Box 的前导、尾随、topSpace 和 bottomSpace 放到了 Green Box 中。 我调整黄色框大小的代码是:
- (void) resizeViewWithZoomInAnimation: (UIView*)view duration:(float)secs option:(UIViewAnimationOptions) option
//sets the new width and height of deal's view
float newWidth = view.superview.frame.size.width - 20;
float newHeight = view.superview.frame.size.height - 20;
[UIView animateWithDuration:secs delay:0.0 options:option
animations: ^
switch ([view tag])
case 1:
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, newWidth, newHeight)];
break;
case 2:
[view setFrame:CGRectMake(CGRectGetMaxX(view.frame),CGRectGetMinY(view.frame), -newWidth , newHeight)];
break;
case 3:
[view setFrame:CGRectMake(CGRectGetMinX(view.frame),CGRectGetMaxY(view.frame), newWidth , -newHeight)];
break;
case 4:
[view setFrame:CGRectMake(CGRectGetMaxX(view.frame),CGRectGetMaxY(view.frame), -newWidth, -newHeight)];
break;
completion:nil];
这应该是 zoomIn 动画的预期结果:
【问题讨论】:
你怎么知道它不起作用?如果调整 UIImageView 的大小,它不一定会调整 UIImageView 显示的 image 的大小。因此,也许图像视图正在按照您的预期调整大小。一种查找方法:为图像视图提供背景颜色,以便您可以看到它的真实位置,而与它包含的图像无关。 但是,如果 UIImageView 真的没有在调整其父视图的大小时被调整大小,那么是的,你的约束有问题。 我之所以设置绿色背景色是为了测试它是否工作正常。问题是,无论我施加什么限制,它都不起作用。你能提出什么建议吗?谢谢 如果绿色框根本不动,在我看来,您对错误的事物进行了限制(即,没有限制作为其超级视图的黄色框)。在 Interface Builder 中为您的视图提供有用的标签,以便约束清楚地告诉您它们正在连接哪些视图。 哦,还有一件事。确保您的视图层次结构是正确的。绿色和黄色框不应该只是主视图(兄弟)的子视图:确保绿色框在内部黄色框(作为它们的子视图),而不仅仅是在它们前面。 【参考方案1】:当尝试使用自动布局制作动画时,您应该不要直接更改视图的框架。相反,您应该为约束的变化设置动画。
要访问情节提要中的约束,您只需 create IBOutlets 即可。
[containerView layoutIfNeeded]; // complete pending layout operations (optional)
[UIView animateWithDuration:1.0 animations:^
// Update constraints
self.viewConstraint1.constant = NEW_VALUE;
self.viewConstraint2.constant = NEW_VALUE;
// Animate the changes
[containerView layoutIfNeeded];
];
请注意,您通常希望在您尝试制作动画的视图的超级视图(或更高)上调用 layoutIfNeeded。
我建议阅读 Apple 的 official guide 中有关自动布局的更多信息。
【讨论】:
将我的代码切换为以这种方式工作,非常适合调整大小,但到目前为止调用 [UIView animateWithDuration:secs delay:0.0 options:option animations: ^ [myView setNeedsLayout]; // 约束中的动画变化 completion:nil];不会产生任何动画。【参考方案2】:对上述答案的调整,我在 UIViewController 中使用
[self.view layoutIfNeeded];
[UIView animateWithDuration:.5
animations:^
myConstraint.constant = 64;
[self.view layoutIfNeeded];
completion:^(BOOL finished)
// whatever
];
注意更改:Apple 文档建议使用 layoutIfNeeded,并在动画块之前和内部调用它。这样您就可以确保在开始之前清除动画堆栈。
另外,您要在要制作动画的约束的父视图上调用 layoutIfNeeded,而不是在拥有约束的视图上调用。感谢@nkukushkin 的初步回答。
正确设置约束也很重要。 IB 中的“修复约束”工具不需要以适合动画的方式设置它们。对我来说,我必须通过它们并思考我希望依赖项如何工作,这当然是意料之中的,但对于初学者来说可能并不明显(并导致错误)。
【讨论】:
感谢您明确指出在何处进行 layoutIfNeeded 调用。我有一个类似的问题,调整大小工作正常,但没有动画。这解决了它。【参考方案3】:当您使用约束时,会生成预约束。当您对位置和大小进行操作时,请在为视图设置动画时移除约束或执行以下操作:
yourView.translatesAutoresizingMaskIntoConstraints = YES;
【讨论】:
以上是关于通过动画调整 UIView 大小时约束不起作用的主要内容,如果未能解决你的问题,请参考以下文章