GeometryReader 和 .frame 的对齐
Alignment for GeometryReader and .frame
我正在使用 GeometryReader() 和 .frame() 来展示它们的可比性并玩弄它们的宽度。
但是,当宽度小于最小值时,包裹在 GeometryReader() 中的对象没有居中对齐。
演示请参考附件gif。
你能帮我对齐一下吗?
理想:
当前:
struct ExampleView: View {
@State private var width: CGFloat = 50
var body: some View {
VStack {
SubView()
.frame(width: self.width, height: 120)
.border(Color.blue, width: 2)
Text("Offered Width is \(Int(width))")
Slider(value: $width, in: 0...200, step: 5)
}
}
}
struct SubView: View {
var body: some View {
GeometryReader { geometry in
Rectangle()
.fill(Color.yellow.opacity(0.6))
.frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
}
}
}
那是因为 GeometryReader
没有将其子项居中。
您必须通过添加 .position
修饰符或 .offset
.
手动定位 Rectangle
.position
将相对于父级中心移动矩形框的原点。
.offset
不会更改框架,而是会更改渲染(像 CGAffineTransform
一样进行翻译)。
您的 Rectangle
的以下修饰符将在视觉上产生相同的结果(尽管在幕后有所不同):
Rectangle()
.fill(Color.yellow.opacity(0.6))
.frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
或
let rectWidth = max(geometry.size.width, 120)
Rectangle()
.fill(Color.yellow.opacity(0.6))
.frame(width: rectWidth, height: max(geometry.size.height, 120))
.offset(x: ((geometry.size.width - rectWidth) / 2), y: 0)
请注意,您的矩形框超出了其父项的边界。我建议避免这种情况,因为它会导致在屏幕上布置其他 UI 元素时出现各种困难。
您可以反过来构建它(除非您的实际目标只是了解 GeometryReader
的工作原理):
struct ExampleView: View {
@State private var width: CGFloat = 50
var body: some View {
VStack {
let minWidth: CGFloat = 120
let subViewWidth: CGFloat = max(minWidth, width)
SubView(desiredWidth: width)
.frame(width: subViewWidth, height: 120)
.background(.yellow.opacity(0.6))
Text("Offered Width is \(Int(width))")
Slider(value: $width, in: 0...200, step: 5)
}
}
}
struct SubView: View {
let desiredWidth: CGFloat
var body: some View {
Rectangle()
.fill(.clear)
.border(Color.blue, width: 2)
.frame(width: desiredWidth, height: nil)
}
}
在此示例中,SubView
具有黄色填充和最小框架宽度,而内部矩形仅采用滑块上设置的任何宽度。它也不再需要 GeometryReader
了。它的外观和行为相同,但 none 的视图不再超出其父级的范围。
我正在使用 GeometryReader() 和 .frame() 来展示它们的可比性并玩弄它们的宽度。 但是,当宽度小于最小值时,包裹在 GeometryReader() 中的对象没有居中对齐。 演示请参考附件gif。
你能帮我对齐一下吗?
理想:
当前:
struct ExampleView: View {
@State private var width: CGFloat = 50
var body: some View {
VStack {
SubView()
.frame(width: self.width, height: 120)
.border(Color.blue, width: 2)
Text("Offered Width is \(Int(width))")
Slider(value: $width, in: 0...200, step: 5)
}
}
}
struct SubView: View {
var body: some View {
GeometryReader { geometry in
Rectangle()
.fill(Color.yellow.opacity(0.6))
.frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
}
}
}
那是因为 GeometryReader
没有将其子项居中。
您必须通过添加 .position
修饰符或 .offset
.
Rectangle
.position
将相对于父级中心移动矩形框的原点。
.offset
不会更改框架,而是会更改渲染(像 CGAffineTransform
一样进行翻译)。
您的 Rectangle
的以下修饰符将在视觉上产生相同的结果(尽管在幕后有所不同):
Rectangle()
.fill(Color.yellow.opacity(0.6))
.frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
或
let rectWidth = max(geometry.size.width, 120)
Rectangle()
.fill(Color.yellow.opacity(0.6))
.frame(width: rectWidth, height: max(geometry.size.height, 120))
.offset(x: ((geometry.size.width - rectWidth) / 2), y: 0)
请注意,您的矩形框超出了其父项的边界。我建议避免这种情况,因为它会导致在屏幕上布置其他 UI 元素时出现各种困难。
您可以反过来构建它(除非您的实际目标只是了解 GeometryReader
的工作原理):
struct ExampleView: View {
@State private var width: CGFloat = 50
var body: some View {
VStack {
let minWidth: CGFloat = 120
let subViewWidth: CGFloat = max(minWidth, width)
SubView(desiredWidth: width)
.frame(width: subViewWidth, height: 120)
.background(.yellow.opacity(0.6))
Text("Offered Width is \(Int(width))")
Slider(value: $width, in: 0...200, step: 5)
}
}
}
struct SubView: View {
let desiredWidth: CGFloat
var body: some View {
Rectangle()
.fill(.clear)
.border(Color.blue, width: 2)
.frame(width: desiredWidth, height: nil)
}
}
在此示例中,SubView
具有黄色填充和最小框架宽度,而内部矩形仅采用滑块上设置的任何宽度。它也不再需要 GeometryReader
了。它的外观和行为相同,但 none 的视图不再超出其父级的范围。