使用以下内容
@main
struct aspectratioApp: App {
var body: some Scene {
WindowGroup { ContentView().border(.blue, width: 2).padding() }
}
}
并且ContentView
没有aspectRatio
应用修饰符(见下文),结果符合预期,包括Canvas
填充可用空间(我认为这是默认行为),输出canvas size: (243.0, 78.0)
到控制台:
接下来,让我们应用.aspectRatio(isSquare ? 1 : nil, contentMode: isSquare ? .fit : .fill)
修饰符,我认为修饰符的意思是制作Canvas
一个适合的正方形或任何填充可用空间的东西(参见下面带有aspectRatio的ContentView)。从一开始我就得到了一个正方形,Canvas
如下所示:
控制台中会打印一个方形画布大小。切换后,isSquare
画布会保持方形,尺寸会略小一些:
canvas size: (157.0, 157.0)
canvas size: (130.0, 130.0)
我这里漏掉了什么? aspectRatio的文档将aspectRatio 参数记录如下:结果视图使用的宽高比。使用 nil 可在结果视图中保持当前的宽高比。我理解的意思是,如果不应用修饰符,则比例将是原来的。
这不是它的工作原理吗?修改器不是无状态的吗?也就是说,它是否记得画布曾经是正方形,并且现在一直保持这种状态,包括重新启动应用程序?
没有aspectRatio的ContentView
struct ContentView: View {
@State private var isSquare = false
var body: some View {
VStack {
Text("isSquare: \(isSquare)").padding()
Canvas { _, size in print("canvas size: \(size)") }
.border(.teal, width: 2)
.padding()
Toggle(isOn: $isSquare) { Text("Constrain to Square") }.padding()
}
.border(.yellow, width: 2)
.padding()
}
}
带有aspectRatio的ContentView
struct ContentView: View {
@State private var isSquare = false
var body: some View {
VStack {
Text("isSquare: \(isSquare)").padding()
Canvas { _, size in print("canvas size: \(size)") }
.aspectRatio(isSquare ? 1 : nil, contentMode: isSquare ? .fit : .fill)
.border(.teal, width: 2)
.padding()
Toggle(isOn: $isSquare) { Text("Constrain to Square") }.padding()
}
.border(.yellow, width: 2)
.padding()
}
}
我的猜测是默认的纵横比是基于视图的理想大小。
a 的理想尺寸
Canvas
是 10.0 x 10.0。这可以通过单独应用.fixedSize()
a来确认:Canvas
当修改器
.aspectRatio
以 的比例应用时nil
,将使用默认纵横比。基于理想尺寸 10.0 x 10.0, 的默认纵横比为Canvas
正方形。传递
nil
给aspectRatio
并不像.opacity(1)
或.scaleEffect(1)
在哪里它不会改变任何东西。aspectRatio
不是幂等的。文档说:
因此,视图需要具有“当前纵横比”。它如何
aspectRatio
找到它?它向 提供了一个.unspecified
尺寸建议Canvas
,要求其理想尺寸。但是Canvas
应该占用尽可能多的空间,所以它只说 10x10(这也是使用 时的默认值replacingUnspecifiedDimensions
),这没有什么意义,但它最终必须返回一些东西。因此
aspectRatio
接收 10x10,然后说“哦,‘当前纵横比’是 1”,这就是Canvas
即使使用 也会变成正方形的nil
方式aspectRatio
。有关 SwiftUI 如何向视图提供尺寸建议的另一个示例,请参阅我的回答
NSViewRepresentable
通过实现和覆盖,您可以查看视图获得的建议sizeThatFits
。当 SwiftUI 想要为您的视图提出尺寸建议时,它会调用此方法。用这个视图替换
Canvas
并使用aspectRatio
。您将看到第一个提案是width: nil, height: nil
- 也称为.unspecified
提案。如果您删除aspectRatio
,则不会有任何.unspecified
提案。请注意,VStack
将多次调用它来进行布局。基本上,您需要获取父级的纵横比并将其传递给
aspectRatio
,而不是让 询问Canvas
其大小。例如,您可以这样做: