动态 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 显示了视图的基本布局。
所以现在的问题是,UIStackView
s 是解决此问题的正确方法还是仅使用约束(例如使用 SnapKit
)是更好的方法?即使使用UIStackView
,我也可能需要有很多约束才能满足要求。
所以也许我应该只拥有一个 addNewView
函数来更新所有约束并在 UIView.animate
块中调用 layoutIfNeeded
以使视图的转换向下推其他视图并且最后一个视图被推出?
你们怎么看?如果存在已经做类似事情的框架,我也将不胜感激。
【问题讨论】:
我希望Q&A 作为起点对您有所帮助... 这种动态的任何东西都可能需要约束和 UIStackviews。您可以在将视图添加到堆栈视图之前向视图添加宽度约束,并且堆栈视图将尊重这些约束。但这是一个非常广泛的问题——您只需要编写代码并使其工作即可。 【参考方案1】:这是一种选择。您需要一些代码来管理添加/删除视图,但这应该不难。注释跟在图片后面:
首先将视图 A、视图 B 和视图 C 放置到主视图上。不用担心大小或定位,也不要给它们任何约束……StackView 会处理所有这些。
选择 B 和 C 并将它们嵌入到 Vertical StackView 中。 Alignment: Fill
、Distribution: Fill Equally
和 Spacing: 8
接下来,选择 A 和刚刚创建的 StackView,并将 它们 嵌入到 Vertical StackView 中。还使用Alignment: Fill
、Distribution: Fill Equally
和Spacing: 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 与普通约束的主要内容,如果未能解决你的问题,请参考以下文章