动态 UIStackView 与普通约束

Posted

技术标签:

【中文标题】动态 UIStackView 与普通约束【英文标题】:Dynamic UIStackView vs. plain constraints 【发布时间】:2017-03-19 14:11:25 【问题描述】:

我正在尝试使用UIStackView 构建一个堆栈视图,它始终最多显示 3 个视图,但也可以同时显示一个、1 个或 2 个视图。

整个堆栈视图应该是动态的。一开始,堆栈视图是空的。另一个函数将在顶部添加一个带有stackView.insertArrangedSubview(at: 0) 的新视图。如果添加了另一个视图,那么索引 0 处的前一个视图应该被推送到索引 1。这就是我选择 UIStackView 的原因,因为它负责对现有视图进行重新排序。

当第三个视图被推入时,另外两个将再次向下移动一个插槽。现在,如果第四个视图被推入,所有之前的三个视图将再次向下移动,但第四个将从堆栈视图中移除。

这里有一个额外的小条件:

第一个索引处的视图应始终是其余 2 个视图大小的两倍。所以第一个视图应该是整个堆栈视图的 50%。因此,索引 1 和 2 处的视图高度应为 25%。

如果一个新视图被推入,当前位于索引 0 的视图将因此必须缩小,向下移动到中间,然后移动到堆栈视图的索引 1。

这个想法类似于Growl Notification System 的工作方式。

image 显示了视图的基本布局。

所以现在的问题是,UIStackViews 是解决此问题的正确方法还是仅使用约束(例如使用 SnapKit)是更好的方法?即使使用UIStackView,我也可能需要有很多约束才能满足要求。

所以也许我应该只拥有一个 addNewView 函数来更新所有约束并在 UIView.animate 块中调用 layoutIfNeeded 以使视图的转换向下推其他视图并且最后一个视图被推出?

你们怎么看?如果存在已经做类似事情的框架,我也将不胜感激。

【问题讨论】:

我希望Q&A 作为起点对您有所帮助... 这种动态的任何东西都可能需要约束和 UIStackviews。您可以在将视图添加到堆栈视图之前向视图添加宽度约束,并且堆栈视图将尊重这些约束。但这是一个非常广泛的问题——您只需要编写代码并使其工作即可。 【参考方案1】:

这是一种选择。您需要一些代码来管理添加/删除视图,但这应该不难。注释跟在图片后面:

首先将视图 A、视图 B 和视图 C 放置到主视图上。不用担心大小或定位,也不要给它们任何约束……StackView 会处理所有这些。

选择 B 和 C 并将它们嵌入到 Vertical StackView 中。 Alignment: FillDistribution: Fill EquallySpacing: 8

接下来,选择 A 和刚刚创建的 StackView,并将 它们 嵌入到 Vertical StackView 中。还使用Alignment: FillDistribution: Fill EquallySpacing: 8 设置此 StackView

现在,选择这个新创建的 StackView - “最顶层” StackView - 并根据需要为其设置约束...这里我将 Leading、Top、Trailing 和 Bottom 都设置为 16。

现在,您只需要以下代码:

func addView(newView: UIView) -> Void 

    // if ViewC has a subview, remove its subview
    // if ViewB has a subview, move ViewB's subview to ViewC
    // if ViewA has a subview, move ViewA's subview to ViewB
    // add newView as a subview of ViewA


呃...试图对此非常清楚...视图 A、B 和 C 将始终存在,因为您在此处看到它们(背景清晰,因此您看不到它们)。当您添加/删除/移动“新”视图时,您将它们添加为 A、B 和 C 的 子视图。有意义吗?

【讨论】:

以上是关于动态 UIStackView 与普通约束的主要内容,如果未能解决你的问题,请参考以下文章

UIStackView 中的图像未四舍五入

界面生成器中带有空 UIStackView 的 UIScrollView 的约束错误

使用约束对动态生成的视图进行动画处理

UIStackView 调整我的视图大小

UIStackView 动态高度图片

不同 UIStackView 的子视图之间的等高约束