Published on

fixedSize

Authors

Fixes this view at its ideal size.

强制展示完整视图

强制一个视图以理想尺寸进行呈现

fixedSize

The fixedSize Modifier fixes the size of modified view at its ideal size. fixedSize修改器的作用是:可将修改后视图的尺寸强制为理想尺寸。

那么,什么是理想尺寸呢?理想尺寸是指一个视图在不受父视图限制的情况下,能够完全展示其内容所需的最小尺寸。

什么是ideal size 理想尺寸

Most of time, ideal size for any view is a size that is large enough to fit the content of that view. 大多数情况下,任何视图的理想尺寸都是足以容纳该视图内容的尺寸。

下面是一些视图的理想尺寸示例:

VStack {
            //1
            Circle()
                .fixedSize()
                .border(.pink)
            //2
            Toggle("Toggle", isOn: .constant(true))
                .fixedSize()
                .border(.pink)
            //3
            DatePicker("Calendar",
                       selection: .constant(.now))
            .fixedSize()
            .border(.pink)

            //4
            Text("Curabitur blandit tempus porttitor. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.")
                .fixedSize()
                .border(.pink)
            //5
            Slider(value: $sliderValue)
                .tint(.mint)
                .border(.pink)
            //6
            Slider(value: $sliderValue)
                .tint(.mint)
                .fixedSize()
                .border(.pink)
        }

运行后的效果如下:

An ideal size from various views 我们可以看到对于长文本,如果加上fixedSize,那么它会只显示一行,多的部分会超出当前屏幕。
对于Slider,如果加上fixedSize,其理想尺寸的宽度会缩小到很小的一个空间,如果不加上fixedSize会把宽度拉伸到尽可能长的尺寸。
因此,我们可以得出以下结论,对于不同的SwiftUI View,其理想尺寸的机制是不同的。我们需要去区别对待。

fixSize Modifier

这个修饰器有两个变体,一个接受两个参数horizontalvertical,另一个是一个参数都没有。

@inlinable public func fixedSize() -> some View
@inlinable public func fixedSize(horizontal: Bool, vertical: Bool) -> some View

fixedSize() 变体其是方法 .fixedSize(horizontal: true, vertical: true)的convenience method

要想比较好的理解fixSize的使用效果,我们最好以一个比较长的Text为例来举例,通过修改不同的fixSize的参数,来看最终的效果。

1.不添加fixedSize,或者添加.fixedSize(horizontal: false, vertical: false)

Text("Curabitur blandit tempus porttitor.\nFusce dapibus, tellus ac cursus commodo.\nTortor mauris condimentum nibh.\nUt fermentum massa justo sit amet risus.\nPraesent commodo cursus magna.\nVel scelerisque nisl consectetur et.")
            .fixedSize(horizontal: false, vertical: false)
            .border(.blue)
            .frame(width: 200, height: 200)
            .border(.pink)
其效果如下: swiftui-text-fixed-size-2

2.添加.fixedSize(horizontal: false, vertical: true) ideal height

我们要求Text在vertical轴向上呈现理想状态,在horizontal轴向上继续使用具有明确数值的建议尺寸宽度(100)。

Text("Curabitur blandit tempus porttitor.\nFusce dapibus, tellus ac cursus commodo.\nTortor mauris condimentum nibh.\nUt fermentum massa justo sit amet risus.\nPraesent commodo cursus magna.\nVel scelerisque nisl consectetur et.")
            .fixedSize(horizontal: false, vertical: true)
            .border(.blue)
            .frame(width: 200, height: 200)
            .border(.pink)

fixedSize 中的 horizontal 参数为false,在水平方向的宽度上,它会尊重父节点,不会超出该区域。 fixedSize 中的 vertical 参数为 true, 在垂直方向的高度上,可以无限增长,以适应其内容。

其效果如下: swiftui-text-fixed-size-1

3.添加.fixedSize(horizontal: true, vertical: false) ideal width

Text("Curabitur blandit tempus porttitor.\nFusce dapibus, tellus ac cursus commodo.\nTortor mauris condimentum nibh.\nUt fermentum massa justo sit amet risus.\nPraesent commodo cursus magna.\nVel scelerisque nisl consectetur et.")
            .fixedSize(horizontal: true, vertical: false)
            .border(.blue)
            .frame(width: 200, height: 200)
            .border(.pink)

这将使文本视图占据其理想宽度,即文本的最大宽度。在本例中就是第二句 “Fusce dapibus, tellus ac cursus commodo”。

其效果如下: swiftui-text-fixed-size-3

4.添加.fixedSize(horizontal: true, vertical: true)

Text("Curabitur blandit tempus porttitor.\nFusce dapibus, tellus ac cursus commodo.\nTortor mauris condimentum nibh.\nUt fermentum massa justo sit amet risus.\nPraesent commodo cursus magna.\nVel scelerisque nisl consectetur et.")
            .fixedSize(horizontal: true, vertical: true)
            .border(.blue)
            .frame(width: 200, height: 200)
            .border(.pink)
其效果如下: swiftui-text-fixed-size-4

我们可以发现,.fixedSize(horizontal: true, vertical: false).fixedSize(horizontal: true, vertical: true)的效果是一样的。

如果我们对Text添加.fixedSize(horizontal: true, vertical: true),那么它的宽度和高度都会被限制在理想尺寸内。其达到的效果是固定视图的大小,使其完全显示其内容。不会因为父视图的尺寸而缩放或截断。

在SwiftUI中的常见使用场景

Hacking with Swift 中有一个关于如何使两个视图的宽度或高度相同的例子,使用了fixedSize修饰符。 How to make two vies the same width or heigth

有两种用法: 在vstack中使用fixedSize修饰符,确保两个视图的宽度相同。

VStack {
  VStack {
            Text("This is a long text that will take up more space")
                .frame(maxWidth: .infinity)
                .border(.blue)
            Image(systemName: "star.fill")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(maxWidth: .infinity)
                .border(.green)
            Slider(value: $sliderValue)
                .tint(.mint)
                .border(.pink)
        }
        .padding()
        .border(.yellow)
        .fixedSize(horizontal: true, vertical: false)
}

其中有两个关键的地方

  1. 设置子视图的 frame 的 maxWidth: .infinity,确保它们可以扩展到父视图的最大宽度。
  2. VStack上使用.fixedSize(horizontal: true, vertical: false),确保VStack的宽度是理想的宽度,而不是被父视图限制。

其效果如下: FixedSize