我想创建一个“添加新的信用卡viewController”。 我们不希望一次性提供所有必填字段的用户恶化。 此操作包含几个步骤。 在每一步中,视图控制器都会显示一个新的子视图(包含一个或多个文本字段)并折叠旧的子视图(在验证文本后的当前文本字段)。
我在故事板上创建了ViewController。并将所有子视图放在另一个上面。
我已经在storyBoard上创建了所有约束,每个子视图都剪辑到上面的子视图等。
即:
NSMutableArray *constraints = [[NSLayoutConstraint
constraintsWithVisualFormat:
@"V:|[titleView]-[subtitleView]-[amountView]-[cardNumView]-[cardsImagesView]-[mmYYCvvView]-[billingInfoView]-[buttomView]|"
options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
metrics:nil
views:variableBindings] mutableCopy];
每个子视图都包含一个高度约束。
在每个步骤中,其中一个高度限制设置为零,另一个高度限制从零更改为所需高度。
即:
self.hgtCrtMMYYCvv.constant = showFields? 50 : 0;
self.hgtCrtBillingInfo.constant = showFields? 140 : 0;
self.mmYYCvvView.hidden = !showFields;
self.billingInfoView.hidden = !showFields;
我有两个问题:
在不调用layoutIfNeeded
的情况下,初始布局有效,但在更改高度限制后没有更改。
调用layoutIfNeeded
没有将底部视图剪切到最后一个可见的视图 - 将其放置在视图的底部,就像所有子视图一次出现一样,但由于某些子视图被隐藏,因此创建了一个间隙。
更改子视图的高度约束已应用于屏幕,但仍然存在差距。
请告知。
答案 0 :(得分:2)
调用" layoutIfNeeded"未将底部视图剪切到最后一个可见的视图 - 将其放置在视图的底部,就像所有子视图一次出现一样
看看你的约束。您已将底部视图的底部固定在其超视图的底部!所以它的底部必须出现在superview的底部,因为这是你指示它做的。
确实,我很惊讶你的约束根本起作用。你基本上已经超定了它们。如果你给每个字段的高度和固定它的顶部和底部,对于每个字段,那么除非你很幸运,否则不可能满足你的约束。超视图的高度是固定的,因此您的约束必须完美地加到该高度。
我将建议一个完整的替代方法,我认为你会发现更容易。不要弄乱个别常量,而是计划每种可能情况的正确(非超定)约束,并将这些约束存储在属性中。现在,当您想要隐藏/显示某个字段时,您只需删除所有约束并在另一个集合中交换。
这也将解决layoutIfNeeded
问题。
碰巧我有一个显示如何执行此操作的实际示例。 (它是用Swift编写的,但我确定你可以在心理上进行补偿。)在我的示例代码中,我们有三个矩形;然后我移除一个矩形并关闭其余两个之间的间隙。准备两套约束是乏味但基本的:
let c1 = NSLayoutConstraint.constraintsWithVisualFormat("H:|-(20)-[v(100)]", options: nil, metrics: nil, views: ["v":v1]) as [NSLayoutConstraint]
let c2 = NSLayoutConstraint.constraintsWithVisualFormat("H:|-(20)-[v(100)]", options: nil, metrics: nil, views: ["v":v2]) as [NSLayoutConstraint]
let c3 = NSLayoutConstraint.constraintsWithVisualFormat("H:|-(20)-[v(100)]", options: nil, metrics: nil, views: ["v":v3]) as [NSLayoutConstraint]
let c4 = NSLayoutConstraint.constraintsWithVisualFormat("V:|-(100)-[v(20)]", options: nil, metrics: nil, views: ["v":v1]) as [NSLayoutConstraint]
let c5with = NSLayoutConstraint.constraintsWithVisualFormat("V:[v1]-(20)-[v2(20)]-(20)-[v3(20)]", options: nil, metrics: nil, views: ["v1":v1, "v2":v2, "v3":v3]) as [NSLayoutConstraint]
let c5without = NSLayoutConstraint.constraintsWithVisualFormat("V:[v1]-(20)-[v3(20)]", options: nil, metrics: nil, views: ["v1":v1, "v3":v3]) as [NSLayoutConstraint]
self.constraintsWith.extend(c1)
self.constraintsWith.extend(c2)
self.constraintsWith.extend(c3)
self.constraintsWith.extend(c4)
self.constraintsWith.extend(c5with)
self.constraintsWithout.extend(c1)
self.constraintsWithout.extend(c3)
self.constraintsWithout.extend(c4)
self.constraintsWithout.extend(c5without)
NSLayoutConstraint.activateConstraints(self.constraintsWith)
但是,当需要将中间视图交换到界面或从界面中取出时,就会得到回报:它是微不足道的。只需删除或插入它,然后删除所有约束,然后插入适合我们已经准备好的情境的全新约束集:
@IBAction func doSwap(sender: AnyObject) {
if self.v2.superview != nil {
self.v2.removeFromSuperview()
NSLayoutConstraint.deactivateConstraints(self.constraintsWith)
NSLayoutConstraint.activateConstraints(self.constraintsWithout)
} else {
self.view.addSubview(v2)
NSLayoutConstraint.deactivateConstraints(self.constraintsWithout)
NSLayoutConstraint.activateConstraints(self.constraintsWith)
}
}
多组约束的准备是繁琐的,但可以通过规则来完成,即约束可以是机器生成的"在一个循环(写这个留给你的练习)。根据一个简单的规则再次交换约束,因为只有一个集合适合您希望显示/隐藏的特定字段集。因此,一旦设置完成,它将比您现在所做的更简单,更易于维护。