iOS - 约束在 viewdidload 中以意想不到的方式动画?
Posted
技术标签:
【中文标题】iOS - 约束在 viewdidload 中以意想不到的方式动画?【英文标题】:iOS - constraints animate in an unexpected way in viewdidload? 【发布时间】:2013-11-01 17:49:09 【问题描述】:我正在练习自动布局并学习动画约束。
我的第一个问题是。如果我动态添加视图,将它们的约束动态添加到父视图似乎很麻烦。有没有什么干净的方法可以实现灵活的布局,可以通过编程方式添加和删除视图?或者这是否意味着我应该为我想要完成的事情想一个更简单的解决方案?
第二个问题。我在代码中创建了两个视图和一些约束。我只是想在加载时调整第一个视图的高度约束,使其变短,而第二个视图将相应地向上移动。
这里有一些代码:
first = [[UIView alloc]initWithFrame:CGRectZero];
[first setBackgroundColor:[UIColor blueColor]];
[first setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:first];
UIView *second = [[UIView alloc]initWithFrame:CGRectZero];
[second setBackgroundColor:[UIColor redColor]];
[second setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:second];
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:first attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:20];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:first attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:-20];
top = [NSLayoutConstraint constraintWithItem:first attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:40];
height = [NSLayoutConstraint constraintWithItem:first attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:80];
[self.view addConstraints:@[leading,trailing,top,height]];
[height setConstant:10];
[UIView animateWithDuration:0.5 animations:^
[self.view layoutIfNeeded];
];
好的,所以在底部运行我的动画.. 我的第二个视图已经定位在动画结束时的位置。第一个视图从左上角扩展到右下角。它以对角线进行动画处理,最终高度为 10。
谁能解释这种行为。我注意到如果我分配约束,并让它们在 IBAction(按钮触摸)上进行动画处理,那么它将按预期进行动画处理。
【问题讨论】:
【参考方案1】:第二个问题。你为什么要在viewDidLoad
中更改动画?此时我们知道视图已加载,但它可能没有布局并且绝对不会对用户可见;考虑viewDidLayoutSubviews
方法中的约束布局变化。
关于第一个问题。大卫 H 的回答是一种方式……而且是一种非常好的方式。为了提供不同的选项,我使用constraintsWithVisualFormat:options:metrics:views:
,它允许我指定视图,然后在所有视图中创建所有必要的约束。它可以是一种更简单的跨多个视图创建约束的方法。取决于您正在做什么,一种方式可能更适合您的需求。
编辑根据评论...
对于必须打破约束的东西,您仍然需要在创建新约束之前找到并打破约束。没有办法解决这个问题。您要么引用要打破的约束,要么必须遍历对象上的所有约束才能找到它。 A B C 转到 A B 和 C,在那里 B 和 C 之间的约束消失了。使用视觉格式输入 X 可能类似于 @"[B]-20-[X]-20-[C]" ,它将为 B 和 X 之间的 20 点间距创建一个约束,第二个约束将是 X 和 C 之间的 20 点间距。请注意,上面的视觉格式仅指定水平定位/间距。您需要第二行来指定垂直约束。
【讨论】:
我想我的问题是.. 如果我在其他视图之间添加视图.. 就像我有视图 A B C 然后我想在它们之间添加一个随机视图 X 这样 A B X C 那么我必须更新视图 B 和 C 的约束,同时为 X 创建约束。这看起来真的很麻烦【参考方案2】:我正在做类似的事情,并且可以扩展该技术。对于每个视图(实际上是任何对象),创建一个具有“视图”和“约束”属性的可变字典。视图只是视图,约束是一个字典数组,包含两个对象、一个“视图”属性和一个“约束”属性。
当您决定添加或拉取视图时,然后找到具有适当视图属性的字典,然后对约束数组进行交互,并将约束(NSLayerConstraint 类型)添加/删除到“视图”中的姐妹“视图”属性字典。
通过这种方式,您可以在一种方法中添加和删除所有适当的约束,无论它们认为它们会影响什么。
显然,您只需要在主视图中引用视图的约束。但是,另一种处理方法是将视图的宽度/高度设置为 0,它仍然存在但不可见。或者将其 alpha 更改为 0。
【讨论】:
以上是关于iOS - 约束在 viewdidload 中以意想不到的方式动画?的主要内容,如果未能解决你的问题,请参考以下文章