取消隐藏后如何保留堆栈视图子项的约束?
Posted
技术标签:
【中文标题】取消隐藏后如何保留堆栈视图子项的约束?【英文标题】:How to retain constraints for a Stack View's child after unhiding? 【发布时间】:2020-06-04 17:10:44 【问题描述】:有一个堆栈视图,其中包含三个标签并具有以下约束:
高度 = 300 顶部 = 安全区域 + 50 尾随/前导 = 0以及以下属性:
轴 -> 垂直 对齐 -> 居中 分布 -> 等间距标签 3(蓝色)有一个变化:对于紧凑型高度尺寸类,已安装属性被禁用(通过属性检查器配置)。这使它隐藏在 iPhone 上的水平方向:
当应用启动时,所有标签在屏幕上都有正确的位置。旋转到水平方向并返回后,Label 3 放置在 Stack View 的左上角,而其他标签正确对齐:
Xcode View Hierarchy 调试器显示标签 3 重新出现后没有任何 UIStackView
相关约束,并且旁边的警告显示“Position is ambiguous”:
标签 3 似乎在被隐藏并再次显示后失去了与 Stack View 相关的所有约束。
【问题讨论】:
为什么要直接在UIStackView
中添加约束?如果有的话,您应该将它们添加到 UIView
内的 UIStackView
内。但这会导致很多问题。你真的应该嵌套UIStackView
。
目前的约束只是定义堆栈视图本身的位置和高度的约束。据我了解,调试器屏幕截图上可见的约束是由框架动态添加的。我不明白为什么应该有嵌套的堆栈视图,而不是一个具有 3 个子标签的单个视图。
我的错,我以为你出于某种原因手动向所有 UILabel 元素添加约束。
@raindev - 试着澄清你在做什么......你说 “标签 3(蓝色)有一个变化:如果高度特征是紧凑的,它就没有安装,使它隐藏在iPhone 上的水平方向” --- 你设置了什么约束来“让它隐藏”?显示包含所有约束的 Storyboard 布局。
@DonMag,通过 Attributes Inspector 配置的 Compact 高度尺寸类的 Installed 属性有一个变体,更新了问题中的措辞。还添加了故事板屏幕截图。我希望它能把问题弄清楚。
【参考方案1】:
您不能为此使用installed
属性,因为它会向超级视图添加/删除视图。这对于 StackView 来说还不够好,因为它需要使用 addArrangedSubview()
添加子视图。
一个简单的解决方案是为您的标签创建一个出口,并在旋转时隐藏/显示它:
@IBOutlet private var label3: UILabel!
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
super.willTransition(to: newCollection, with: coordinator)
label3.isHidden = newCollection.verticalSizeClass == .compact
【讨论】:
感谢 Gereon 的回答!您能否就installed
属性的用途提供一些指导?鉴于它的名称,在网上很难找到有关它的信息,并且在UIView
的文档中也没有提到它。
供以后参考:willTransition
是UIContentContainer
的实例方法,UIViewController
实现的与大小/特征更改相关的逻辑协议。
我找不到任何当前文档,但installed
纯粹是一个 IB 概念,而不是 UIView 上的属性。引用此old doc:“仍然会创建已卸载视图的运行时对象。但是,视图和任何相关约束都不会添加到视图层次结构中,并且视图具有 nil 的超级视图属性。这与隐藏不同. 隐藏的视图与任何相关的约束一样位于视图层次结构中。”【参考方案2】:
一种简单得多的方法 - 在 Hidden
属性上设置特征变化。
这是你的布局:
选择底部标签,然后在“属性检查器”窗格中,单击Hidden
旁边的+
按钮:
将变体更改为:
您现在可以选择一个新的Hidden
变体:
这是您在旋转到 wC hC 时得到的结果:
正如这些图片所示,您甚至可以在 Storyboard 中看到结果...在运行时无需等待代码。
【讨论】:
感谢另一个很好的回答!引用UIStackView
的文档:“每当视图被添加、删除或插入到arrangedSubviews
数组中,或者每当排列的子视图的isHidden
属性之一发生变化时,堆栈视图都会自动更新其布局。”由于子视图从未从arrangedSubviews
中删除,因此在不更新arrangedSubviews
的情况下将其作为UIStackView
的子视图添加回来没有问题。以上是关于取消隐藏后如何保留堆栈视图子项的约束?的主要内容,如果未能解决你的问题,请参考以下文章