StackView 布局并排放置(如 zStack)
StackView layout side by side & on Top of each other (like zStack)
我目前有这个界面,我将 MapView 和 UIView 放在彼此之上。 UIView 是我放置图表叠加层的地方(例如:心率)。
当设备处于纵向模式时,这很好。但是,我想在横向模式下探索不同的布局,其中 UIView(HR Chart)和 MapView 并排。
这在 Interface Builder 中可行吗?还是仅在代码中? (我只想使用 UIKit 来更好地支持较低的操作系统)
注意:我在 IB 中尝试过,但似乎无法弄清楚如何获取堆栈,以便 MapView 和 UIView 在纵向模式下彼此重叠。
这是现在的样子。但我想在横向模式下并排显示图表和地图。
编辑以澄清纵向模式下的当前布局和横向模式下的预期结果。
布局看起来如何。
这可以通过在堆栈视图上使用 Trait Variations,在垂直和水平之间更改轴来完成。
考虑一下这种布局 - 我已经为标签提供了背景颜色以帮助可视化:
- 每个“名称/值”标签集都在垂直堆栈视图中
- 每“对”“组”——功率/斜率、距离/经过时间、心率/踏频——也在它们自己的垂直堆栈视图中
- 3 个“对”在水平堆栈视图中
Select RedPairStack
并在“属性检查器”窗格中单击轴左侧的 +
图标:
从该弹出窗口中,将 Width
更改为 Any
,将 Height
更改为 Compact
,然后单击 Add Variation
:
对于新的 hC
变体,select Horizontal
:
对 GreenPairStack
和 BluePairStack
执行相同的操作。
现在,当设备具有常规高度时,这三个堆栈视图将使用垂直轴...在紧凑高度中,它们将使用水平轴。
结果如下:
这是情节提要的来源,因此您可以检查所有内容:https://pastebin.com/dqNp8CcC
编辑 - 评论后...
要获得 side-by-side,我们需要进行一些更改:
看起来很相似,但是:
- 在
UIView
- “PairsContainerView”(哈密瓜背景) 中嵌入了“label/value”水平堆栈
- 在垂直堆栈视图中嵌入该视图和地图视图
我从 PairStacks 中删除了 Trait 变体,然后将 HorizontalStack 约束到“PairsContainerView”的所有 4 个边
结果一开始看起来不错,但旋转时标签会被拉长。因此,我们添加了几个新的特征变异。
首先,将所有标签的 Content Hugging Priority 设置为 Required。
接下来,对于 Compact Height (hC
) 特性,我们将 CenterY 约束添加到 HorizontalStack,并删除 Top 和 Bottom 约束。
这是新结果:
并删除颜色:
由于您没有提供您想要您的布局外观的图像,这可能足以让您正在路上。
新故事板来源:https://pastebin.com/TkVbNUVE
编辑 2
从上面的第一个例子开始...
添加一个 UIView
作为地图视图的兄弟并将其自定义 Class 分配给 HeartRateView
:
这是我的快速 HeartRateView
(红色波浪线):
class HeartRateView: UIView {
let shapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 1.0
let pth = UIBezierPath()
let topY: CGFloat = 40.0
var pt: CGPoint = CGPoint(x: 0.0, y: topY)
pth.move(to: pt)
for _ in 1...30 {
pt.x += 2
pt.y = topY + CGFloat.random(in: 0...40)
pth.addLine(to: pt)
}
shapeLayer.path = pth.cgPath
}
}
将这些约束添加到 HeartRateView:
- 顶部等于 MapView 顶部
- 行距等于 MapView 行距
- 宽度等于 MapView 宽度
- 高度等于 MapView 高度
如您所料,这会将 HeartRateView“覆盖”在 MapView 上。
现在,在 Storyboard 中,将 Orientation 切换为 Landscape 并单击“Vary for Traits”按钮。从该弹出窗口中,select Height
Select Document Outline 窗格中的 MapView,以及 Size Inspector 窗格中的 MapView,select Trailing to Safe Area 和 Leading to Heart Rate View 约束:
点击键盘上的删除 - 它将删除仅此特征变体的约束。应如下所示:
您的视图应如下所示:
Select 心率视图并将其尾部限制在安全区域(我在所有内容上使用 4 点填充)。您的视图现在应该如下所示(心率视图具有清晰的背景,因此我们只能看到 select 离子手柄):
现在添加一个从 MapView Trailing 到 HeartRateView Leading 的约束(4 个用于小填充):
因为HeartRateView仍然被约束为MapView的Equal Width,所以他们会自动填充宽度。
最后一步,点击完成变化
现在我们得到这个输出:
这是第三个故事板来源:https://pastebin.com/2hPXisAH
我目前有这个界面,我将 MapView 和 UIView 放在彼此之上。 UIView 是我放置图表叠加层的地方(例如:心率)。
当设备处于纵向模式时,这很好。但是,我想在横向模式下探索不同的布局,其中 UIView(HR Chart)和 MapView 并排。
这在 Interface Builder 中可行吗?还是仅在代码中? (我只想使用 UIKit 来更好地支持较低的操作系统)
注意:我在 IB 中尝试过,但似乎无法弄清楚如何获取堆栈,以便 MapView 和 UIView 在纵向模式下彼此重叠。
这是现在的样子。但我想在横向模式下并排显示图表和地图。
编辑以澄清纵向模式下的当前布局和横向模式下的预期结果。
布局看起来如何。
这可以通过在堆栈视图上使用 Trait Variations,在垂直和水平之间更改轴来完成。
考虑一下这种布局 - 我已经为标签提供了背景颜色以帮助可视化:
- 每个“名称/值”标签集都在垂直堆栈视图中
- 每“对”“组”——功率/斜率、距离/经过时间、心率/踏频——也在它们自己的垂直堆栈视图中
- 3 个“对”在水平堆栈视图中
Select RedPairStack
并在“属性检查器”窗格中单击轴左侧的 +
图标:
从该弹出窗口中,将 Width
更改为 Any
,将 Height
更改为 Compact
,然后单击 Add Variation
:
对于新的 hC
变体,select Horizontal
:
对 GreenPairStack
和 BluePairStack
执行相同的操作。
现在,当设备具有常规高度时,这三个堆栈视图将使用垂直轴...在紧凑高度中,它们将使用水平轴。
结果如下:
这是情节提要的来源,因此您可以检查所有内容:https://pastebin.com/dqNp8CcC
编辑 - 评论后...
要获得 side-by-side,我们需要进行一些更改:
看起来很相似,但是:
- 在
UIView
- “PairsContainerView”(哈密瓜背景) 中嵌入了“label/value”水平堆栈
- 在垂直堆栈视图中嵌入该视图和地图视图
我从 PairStacks 中删除了 Trait 变体,然后将 HorizontalStack 约束到“PairsContainerView”的所有 4 个边
结果一开始看起来不错,但旋转时标签会被拉长。因此,我们添加了几个新的特征变异。
首先,将所有标签的 Content Hugging Priority 设置为 Required。
接下来,对于 Compact Height (hC
) 特性,我们将 CenterY 约束添加到 HorizontalStack,并删除 Top 和 Bottom 约束。
这是新结果:
并删除颜色:
由于您没有提供您想要您的布局外观的图像,这可能足以让您正在路上。
新故事板来源:https://pastebin.com/TkVbNUVE
编辑 2
从上面的第一个例子开始...
添加一个 UIView
作为地图视图的兄弟并将其自定义 Class 分配给 HeartRateView
:
这是我的快速 HeartRateView
(红色波浪线):
class HeartRateView: UIView {
let shapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 1.0
let pth = UIBezierPath()
let topY: CGFloat = 40.0
var pt: CGPoint = CGPoint(x: 0.0, y: topY)
pth.move(to: pt)
for _ in 1...30 {
pt.x += 2
pt.y = topY + CGFloat.random(in: 0...40)
pth.addLine(to: pt)
}
shapeLayer.path = pth.cgPath
}
}
将这些约束添加到 HeartRateView:
- 顶部等于 MapView 顶部
- 行距等于 MapView 行距
- 宽度等于 MapView 宽度
- 高度等于 MapView 高度
如您所料,这会将 HeartRateView“覆盖”在 MapView 上。
现在,在 Storyboard 中,将 Orientation 切换为 Landscape 并单击“Vary for Traits”按钮。从该弹出窗口中,select Height
Select Document Outline 窗格中的 MapView,以及 Size Inspector 窗格中的 MapView,select Trailing to Safe Area 和 Leading to Heart Rate View 约束:
点击键盘上的删除 - 它将删除仅此特征变体的约束。应如下所示:
您的视图应如下所示:
Select 心率视图并将其尾部限制在安全区域(我在所有内容上使用 4 点填充)。您的视图现在应该如下所示(心率视图具有清晰的背景,因此我们只能看到 select 离子手柄):
现在添加一个从 MapView Trailing 到 HeartRateView Leading 的约束(4 个用于小填充):
因为HeartRateView仍然被约束为MapView的Equal Width,所以他们会自动填充宽度。
最后一步,点击完成变化
现在我们得到这个输出:
这是第三个故事板来源:https://pastebin.com/2hPXisAH