隐藏互斥子视图后调整容器 UIView 的大小以匹配可见子视图的高度
Resize container UIView to match height of visible subview after hiding mutually exclusive subview
ParentView 包含 ChildView1 和 ChildView2。这些子视图具有不同的高度。
ChildView1 比 ChildView2 高。仅显示一个子视图,例如,如果 ChildView1 可见,则隐藏 ChildView2。 ChildView1 和 ChildView2 都使用自定义 XIB。
两个子视图 "drive" ParentView 的高度,即 AutoLayout 约束的连接方式使得 ParentView 与 ChildView1 或 ChildView2 一样高,而不是更高。
问题是隐藏 ChildView1 而显示 ChildView2 与 "shrink" ParentView 不匹配 ChildView2 的高度。它保持在较高的子视图 ChildView1 的高度。
调用 sizeToFit()
和 setNeedsLayout()
并没有改变。
如何在ChildView1隐藏时强制ParentView匹配ChildView2的高度?
您可以将父视图设置为与子视图保持相同的大小
// Match to childView1
CGSize size = childView1.frame.size;
[parentView setFrame:CGRectMake(0,0,size.width,size.height)];
或相反
// Match to childView2
CGSize size = childView2.frame.size;
[parentView setFrame:CGRectMake(0,0,size.width,size.height)];
隐藏视图仍然参与布局。除了隐藏它之外,您还需要停用隐藏视图的约束。
如果您的部署目标是 iOS 9 或更高版本,您可以将父级设置为 UIStackView
。堆栈视图在布局期间自动忽略其隐藏的子项。
更新
您不需要针对所有约束的单独出口。您只需要两个出口系列。您可以将一个插座集合连接到多个对象。演示:
集合最终连接到故事板中的多个对象:
然后您可以使用一条语句激活或停用一组约束:
class ViewController: UIViewController {
@IBOutlet var pinkConstraints: [NSLayoutConstraint]!
@IBOutlet var greenConstraints: [NSLayoutConstraint]!
func showPink() {
NSLayoutConstraint.deactivateConstraints(greenConstraints)
NSLayoutConstraint.activateConstraints(pinkConstraints)
}
func showGreen() {
NSLayoutConstraint.deactivateConstraints(pinkConstraints)
NSLayoutConstraint.activateConstraints(greenConstraints)
}
}
通过在 ParentView 和 ChildView1/ChildView2 之间插入中间视图解决了问题。这样,ChildView1 驱动其包含视图的高度,而不是 ParentView,这与 ChildView2 相同。也许不是最干净的,但它正在工作。 Rob 关于使用 UIStackView 的建议似乎很理想,但它只需要放弃对 iOS 8 的支持,这对于应用程序来说目前并不实用。
ParentView 包含 ChildView1 和 ChildView2。这些子视图具有不同的高度。
ChildView1 比 ChildView2 高。仅显示一个子视图,例如,如果 ChildView1 可见,则隐藏 ChildView2。 ChildView1 和 ChildView2 都使用自定义 XIB。
两个子视图 "drive" ParentView 的高度,即 AutoLayout 约束的连接方式使得 ParentView 与 ChildView1 或 ChildView2 一样高,而不是更高。
问题是隐藏 ChildView1 而显示 ChildView2 与 "shrink" ParentView 不匹配 ChildView2 的高度。它保持在较高的子视图 ChildView1 的高度。
调用 sizeToFit()
和 setNeedsLayout()
并没有改变。
如何在ChildView1隐藏时强制ParentView匹配ChildView2的高度?
您可以将父视图设置为与子视图保持相同的大小
// Match to childView1
CGSize size = childView1.frame.size;
[parentView setFrame:CGRectMake(0,0,size.width,size.height)];
或相反
// Match to childView2
CGSize size = childView2.frame.size;
[parentView setFrame:CGRectMake(0,0,size.width,size.height)];
隐藏视图仍然参与布局。除了隐藏它之外,您还需要停用隐藏视图的约束。
如果您的部署目标是 iOS 9 或更高版本,您可以将父级设置为 UIStackView
。堆栈视图在布局期间自动忽略其隐藏的子项。
更新
您不需要针对所有约束的单独出口。您只需要两个出口系列。您可以将一个插座集合连接到多个对象。演示:
集合最终连接到故事板中的多个对象:
然后您可以使用一条语句激活或停用一组约束:
class ViewController: UIViewController {
@IBOutlet var pinkConstraints: [NSLayoutConstraint]!
@IBOutlet var greenConstraints: [NSLayoutConstraint]!
func showPink() {
NSLayoutConstraint.deactivateConstraints(greenConstraints)
NSLayoutConstraint.activateConstraints(pinkConstraints)
}
func showGreen() {
NSLayoutConstraint.deactivateConstraints(pinkConstraints)
NSLayoutConstraint.activateConstraints(greenConstraints)
}
}
通过在 ParentView 和 ChildView1/ChildView2 之间插入中间视图解决了问题。这样,ChildView1 驱动其包含视图的高度,而不是 ParentView,这与 ChildView2 相同。也许不是最干净的,但它正在工作。 Rob 关于使用 UIStackView 的建议似乎很理想,但它只需要放弃对 iOS 8 的支持,这对于应用程序来说目前并不实用。