如何使SwiftUI视图完全填充其父视图?

8
以下应该会创建一个边界占据整个屏幕的文本,但似乎什么也没有发生。
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存在的问题,还是我漏掉了什么?


你尝试过将你的内容放在ZStack中吗?创建一个背景视图 - RectangleImage或其他 - 然后将你的其他视图放在上面? - user7014451
1个回答

16

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

简要概括一下Dave详细解释的内容:

  1. 父视图(在本例中为由系统创建并填充屏幕的根视图)向其子视图提议一个尺寸。
  2. 子视图选择自己的尺寸,根据需要消耗所提议的尺寸的多少。
  3. 父视图根据诸如子视图选择的尺寸等各种参数在父视图的坐标空间中定位子视图。

因此,你无法强制一个小的Text填满整个屏幕,因为在第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"))
    }
}
如果您使用包含Color.redTextZStack,则ZStack将包装Color.red,并因此具有其可扩展性:
struct ContentView: View {
    var body: some View {
        ZStack {
            Color.red
            Text("hello")
        }
    }
}

这不会起作用。ZStack 也将从内容中获取大小。一种方法是使用 .frame 修改器设置框架。 - msk
1
我已经修正了我的答案并进行了测试。 - rob mayoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接