我在摆弄一个视图布局-一个图形-在这里我看到在全Swift布局中可以走多远。每个组件都很好,但是组装整个组件并没有达到我想要的效果。我发现,我可以轻松地沿单个堆栈轴限制大小,而不能一次限制两个轴(垂直和水平)。
正如我发现you can align non-siblings with a custom guide一样,我开始接触AlignmentGuides。这将有助于我的目标,但并不能解决定型部分,这是此问题的核心:
是否有一种方法可以基于另一个非同级视图来限制视图的大小?
结构的简化为:
HStack {
CellOneView {
}
CellTwoView {
}
}
HStack {
CellThreeView {
}
CellFourView {
}
}
哪个映射到:
+-----+-----+
| 1 | 2 |
+-----+-----+
| 3 | 4 |
+-----+-----+
是否可以告诉CellFour(与单元格1和2不在同一个HStack中),我希望它将自身约束(并对齐)到单元格CellTwo的宽度?
这不一定严格是网格视图(example of grid view)。在这种情况下,我实际上只关心三个视图-大致映射到单元格1,单元格2和单元格4的区域。我希望单元格1和单元格2的高度相同(可以容易地通过当前HStack
),并且单元2和单元4的宽度相同-这就是我在努力的地方。
答案 0 :(得分:2)
由于您已经开始使用对齐向导,因此可以使用此仪器。这是可能的方法(针对您的抓痒示例):
@State private var width: CGFloat = 10 // < initial value does not much matter
...
HStack {
CellOneView {
}
CellTwoView {
}
.alignmentGuide(VerticalAlignment.center, computeValue: { d in
// for simplicity of demo skipped checking for equality
DispatchQueue.main.async { // << must be async
self.width = d.width // << set limit
}
return d[VerticalAlignment.center]
})
}
HStack {
CellThreeView {
}
CellFourView {
}
.frame(width: self.width) // << apply limit, updated right in next loop
}
答案 1 :(得分:2)
struct CellTwoView: View {
var body: some View {
Rectangle()
.background(
GeometryReader(content: { (proxy: GeometryProxy) in
Color.clear
.preference(key: MyPreferenceKey.self, value: MyPreferenceData(rect: proxy.size))
})
)
}
}
说明-在这里,我已经从使用background View(Color.clear)获得了视图的大小,除非从CellTwoView本身获得了它的大小,否则我将使用此技巧。 “ SwiftUI-View大小的原因由视图本身确定,如果它们具有大小(父级不能像UIKit那样更改大小)。因此,如果我将GeometryReader
与CellTwoView本身一起使用,则GeometryReader
会占用CellTwoView的 parent 中可用的大小。 ->原因-> GeometryReader取决于其父级大小。 (实际上这是另一个主题,也是SwiftUI中的主要内容)
键->
struct MyPreferenceKey: PreferenceKey {
static var defaultValue: MyPreferenceData = MyPreferenceData(size: CGSize.zero)
static func reduce(value: inout MyPreferenceData, nextValue: () -> MyPreferenceData) {
value = nextValue()
}
typealias Value = MyPreferenceData
}
值(及其首选项更改时的处理方式)->
struct MyPreferenceData: Equatable {
let size: CGSize
//you can give any name to this variable as usual.
}
struct ContentView: View {
@State var widtheOfCellTwoView: CGFloat = .zero
var body: some View {
VStack {
HStack {
CellOneView()
CellTwoView ()
.onPreferenceChange(MyPreferenceKey.self) { (prefereneValue) in
self.widtheOfCellTwoView = prefereneValue.size.width
}
}
HStack {
CellThreeView ()
CellFourView ()
.frame(width: widtheOfCellTwoView)
}
}
}
}