自动布局在移除中间视图时如何折叠空间

8

我对如何正确定义约束条件以在删除给定视图时收缩视图之间的空间感到有些困惑。 我已尝试添加垂直约束,并使用大于或等于关系,但似乎满足��束条件的最小距离不受优先考虑。

例如,给定以下布局,其中包含三个约束条件 V:[A]-5-[B]、V:[B]-5-[C] 和 V:[A]-(>=5)-[C]:

[ View A ]
    |
   5 pt
    |
[ View B ]
    |
   5 pt
    |
[ View C ]

删除 B 视图后,我希望它看起来像这样:

[ View A ]
    |
   5 pt
    |
[ View C ]

但是它的样子是这样的:
[ View A ]
    |
   5 pt + 5 pt + height of view B
    |
[ View C ]

4
把英语翻译成中文。请只返回翻译好的文字:+1 表示问题清晰并格式整洁。 - Eugene
你是要移除视图B还是只是隐藏它?你需要在某个时刻将其恢复吗? - Léo Natan
3个回答

9
你可以使用较低的优先级(低于1000),添加 V:[A]-5-[C]。
[superview]
    |
[ View A ]
    |             |
   5 pt (1000)    | 
    |             |
[ View B ]       5 pt (999)
    |             |
   5 pt (1000)    |
    |             |
[ View C ]        

这种方法会产生“无法同时满足约束条件”的警告。另一个缺点是,随着您垂直添加更多视图,它的可扩展性不好。 - Jack Rowlingson
@JackRowlingson 刚刚用这种方法构建了一个测试项目 - 没有警告。看起来你有一些其他的冲突约束条件。猜测你已经将视图 C 捆绑到底部了。 - MANIAK_dobrii

4
如果您希望这个可以实现可扩展性,那么可能需要在代码中进行操作。我通常使用类似以下的代码:
UIView *superView = /* whatever the superview of your views is, probably self.view in a lot of cases */
NSArray *arrViews = [NSArray arrayWithObjects:/* put only the things you want to show in here, do not put the hidden things, and put them in order from top to bottom */, nil];
CGFloat buffer = 5;

[superView addConstraint:[NSLayoutConstraint constraintWithItem:[arrViews objectAtIndex:0] attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superView attribute:NSLayoutAttributeTop multiplier:1 constant:buffer]];
for (int i = 1; i < arrViews.count; i++)
{
     [superView addConstraint:[NSLayoutConstraint constraintWithItem:[arrViews objectAtIndex:i] attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:[arrViews objectAtIndex:i-1] attribute:NSLayoutAttributeBottom multiplier:1 constant:buffer]];
}
[superView addConstraint:[NSLayoutConstraint constraintWithItem:[arrViews lastObject] attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superView attribute:NSLayoutAttributeBottom multiplier:1 constant:-1*(buffer)]]; 

这将在顶部项和其父视图之间以及每个子视图和直接在其上面的子视图之间放置固定间距(大小为buffer),然后在底部视图和父视图之间放置间距。 每次从arrViews中删除项目后,您都需要调用此函数,然后调用[superView needsLayout]。 您还需要确保已以某种方式设置高度约束,否则会出现错误。 如果所有内容的高度都相同,则可以在循环中添加另一行以添加高度约束。

是否有任何途径通过 UIStackView 来实现这个? - QED

1
你需要以编程方式重新连接约束条件,使得视图C视图B的约束指向视图A,并确保从视图A视图B的约束被移除。完成后,在包含这些视图的父视图上调用layoutIfNeeded

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接