删除中间视图时自动布局折叠空间

Posted

技术标签:

【中文标题】删除中间视图时自动布局折叠空间【英文标题】:Autolayout collapsing space when removing intermediate views 【发布时间】:2014-03-13 16:21:54 【问题描述】:

对于如何正确定义在删除给定视图时将折叠视图之间空间的约束,我感到有些困惑。我尝试添加具有大于或等于关系的垂直约束,但是,满足约束的最小距离似乎不是首选。

例如,给定以下具有三个约束的布局 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 ]

【问题讨论】:

+1 表示问题格式清晰整洁 您是删除视图 B 还是隐藏它?你需要在某个时候恢复它吗? 【参考方案1】:

您可以添加 V:[A]-5-[C] 的情人优先级,低于 1000。

[superview]
    |
[ View A ]
    |             |
   5 pt (1000)    | 
    |             |
[ View B ]       5 pt (999)
    |             |
   5 pt (1000)    |
    |             |
[ View C ]        

【讨论】:

这种方法会发送垃圾邮件“无法同时满足约束”。警告。另一个缺点是垂直添加的视图越多,它就不能很好地缩放。 @JackRowlingson 刚刚用这种方法构建了一个测试项目——没有警告。看起来您还有其他一些相互冲突的约束。猜猜你已经以某种方式将视图 C 拉到了底部。【参考方案2】:

如果您希望它具有可扩展性,您可能必须在代码中实现。我使用类似

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]。您还需要确保以某种方式设置了高度限制,否则会出错。如果一切都将是相同的高度,您可以在循环中添加另一行来添加高度约束。

【讨论】:

【参考方案3】:

您需要以编程方式重新连接约束,以便 View C 的约束指向 View B 而不是指向 View A,并确保从 View AView B 的约束已删除。 完成此操作后,在包含这些视图的超级视图上调用 layoutIfNeeded

【讨论】:

以上是关于删除中间视图时自动布局折叠空间的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局删除和重新添加子视图

动态调整视图大小(拖动运动)时自动布局约束中断

使用自动布局删除视图并重新排列其余部分

xcode自动布局隐藏视图占用空间

自动布局:删除视图时相邻视图的后备约束

等宽和设置优先级的自动布局