首页 > 解决方案 > 如何让 SwiftUI 视图完全填充其超级视图?

问题描述

下面应该创建一个Text其边界占据整个屏幕,但它似乎什么都不做。

struct ContentView: View {
    var body: some View {
        Text("foo")
            .relativeSize(width: 1.0, height: 1.0)
            .background(Color.red)
    }
}

以下黑客:

extension View {
    /// Causes the view to fill into its superview.
    public func _fill(alignment: Alignment = .center) -> some View {
        GeometryReader { geometry in
            return self.frame(
                width: geometry.size.width,
                height: geometry.size.height,
                alignment: alignment
            )
        }
    }
}

struct ContentView2: View {
    var body: some View {
        Text("foo")
            ._fill()
            .background(Color.red)
    }
}

然而似乎工作。

这是一个 SwiftUI 错误relativeSize,还是我错过了什么?

标签: swiftswiftui

解决方案


您需要观看WWDC 2019 Session 237: Building Custom Views with SwiftUI,因为 Dave Abrahams 讨论了这个主题,并Text在他的示例中使用。

简要重申戴夫详细解释的内容:

  1. 父级(在这种情况下,由系统创建并填充屏幕的根视图)向其子级建议一个大小。
  2. 孩子选择自己的尺寸,根据需要消耗尽可能多或尽可能少的建议尺寸。
  3. 父级根据包括子级选择的大小在内的各种参数将子级定位在父级的坐标空间中。

因此,您不能强制一个 smallText填充屏幕,因为在第 2 步中,Text将拒绝消耗比适合其内容所需的更多空间。

Color.red不同的是:在第 2 步中,它只是将建议的大小作为自己的大小返回。我们可以称这样的视图为“可扩展的”:它们可以扩展以填充所提供的任何空间。

ZStack也不同:在第 2 步中,它会询问其孩子的尺寸,并根据其孩子的尺寸选择自己的尺寸。我们可以将这样的视图称为“包装”:它们紧紧地包裹着自己的孩子。

因此,如果您将其提升Color.red为由 返回的“主”视图body,并将其放在Text叠加层中,您的ContentView行为将类似于Color.red并且可以扩展:

struct ContentView: View {
    var body: some View {
        Color.red
            .overlay(Text("foo"))
    }
}

如果你使用ZStack包含Color.redandText的 a ,ZStack则将包装Color.red,从而具有它的可扩展性:

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.red
            Text("hello")
        }
    }
}

推荐阅读