在SwiftUI中使VStack充满屏幕的宽度

iel*_*ani 24 xcode ios swift swiftui

给定此代码:

import SwiftUI

struct ContentView : View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Title")
                .font(.title)

            Text("Content")
                .lineLimit(nil)
                .font(.body)

            Spacer()
        }
        .background(Color.red)
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif
Run Code Online (Sandbox Code Playgroud)

导致这种交互:

预习

VStack即使标签/文本组件不需要整个宽度,如何填充屏幕的宽度?

我发现的一个技巧是在结构中插入一个 HStack,如下所示:

VStack(alignment: .leading) {
    HStack {
        Spacer()
    }
    Text("Title")
        .font(.title)

    Text("Content")
        .lineLimit(nil)
        .font(.body)

    Spacer()
}
Run Code Online (Sandbox Code Playgroud)

产生所需的设计:

期望的输出

有没有更好的办法?

sva*_*all 38

尝试将.frame修饰符与以下选项一起使用:

.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: Alignment.topLeading)
Run Code Online (Sandbox Code Playgroud)
    struct ContentView : View {
        var body: some View {
            VStack(alignment: .leading) {
                Text("Hello World")
                    .font(.title)
                Text("Another")
                    .font(.body)
                Spacer()
            }
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
            .background(Color.red)
        }
    }
Run Code Online (Sandbox Code Playgroud)

这被描述为是一个灵活的框架(请参阅文档),它将伸展以填充整个屏幕,并且当它有多余的空间时,它将使其内容居中。

  • 错了 .backgound(Color.red)是框架视图的背景,而不是框架视图中的VStack的背景。(其原因在WWDC视频:P中进行了说明)。如果将.background(Color.green)放在.frame之前,则会看到VStack的宽度仍然适合其内容,而框架的背景是红色...当您将.frame( ...)`,它不是在编辑`VStack`,而是实际上是在创建另一个视图。 (3认同)
  • @Jake 似乎是一场灾难的根源 (3认同)
  • 有一个问题:既然我们有 VStack(alignment: .leading) ,为什么要使用alignment: .topLeading ?感谢分享 (2认同)

Ima*_*tit 38

对于 Swift 5.2 和 iOS 13.4,根据您的需要,您可以使用以下示例之一将您VStack的顶部前导约束和全尺寸框架对齐。

请注意,下面的代码片段都导致相同的显示,但不保证在调试视图层次结构时可能出现的有效帧VStackView元素数量。


一、使用frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:)方法

最简单的方法是设置VStack具有最大宽度和高度的框架,并在 中传递所需的对齐方式frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:)

struct ContentView: View {

    var body: some View {
        VStack(alignment: .leading) {
            Text("Title")
                .font(.title)
            Text("Content")
                .font(.body)
        }
        .frame(
            maxWidth: .infinity,
            maxHeight: .infinity,
            alignment: .topLeading
        )
        .background(Color.red)
    }

}
Run Code Online (Sandbox Code Playgroud)

2.使用Spacers强制对齐

您可以将您的VStack内部嵌入全尺寸HStack并使用尾随和底部Spacers 来强制您的VStack顶部前导对齐:

struct ContentView: View {

    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                Text("Title")
                    .font(.title)
                Text("Content")
                    .font(.body)

                Spacer() // VStack bottom spacer
            }

            Spacer() // HStack trailing spacer
        }
        .frame(
            maxWidth: .infinity,
            maxHeight: .infinity
        )
        .background(Color.red)
    }

}
Run Code Online (Sandbox Code Playgroud)

3. 使用ZStack全尺寸背景View

此示例展示了如何将具有顶部前导对齐的VStack内部嵌入ZStack。请注意如何使用Color视图来设置最大宽度和高度:

struct ContentView: View {

    var body: some View {
        ZStack(alignment: .topLeading) {
            Color.red
                .frame(maxWidth: .infinity, maxHeight: .infinity)

            VStack(alignment: .leading) {
                Text("Title")
                    .font(.title)
                Text("Content")
                    .font(.body)
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

4. 使用 GeometryReader

GeometryReader有以下声明

一个容器视图,将其内容定义为其自身大小和坐标空间的函数。[...] 此视图将灵活的首选大小返回到其父布局。

下面的代码片段显示了如何使用顶部前导约束和全尺寸框架GeometryReader对齐VStack

struct ContentView : View {

    var body: some View {
        GeometryReader { geometryProxy in
            VStack(alignment: .leading) {
                Text("Title")
                    .font(.title)
                Text("Content")
                    .font(.body)
            }
            .frame(
                width: geometryProxy.size.width,
                height: geometryProxy.size.height,
                alignment: .topLeading
            )
        }
        .background(Color.red)
    }

}
Run Code Online (Sandbox Code Playgroud)

五、使用overlay(_:alignment:)方法

如果您想将您的VStack与现有全尺寸顶部的前导约束对齐View,您可以使用overlay(_:alignment:)方法:

struct ContentView: View {

    var body: some View {
        Color.red
            .frame(
                maxWidth: .infinity,
                maxHeight: .infinity
            )
            .overlay(
                VStack(alignment: .leading) {
                    Text("Title")
                        .font(.title)
                    Text("Content")
                        .font(.body)
                },
                alignment: .topLeading
            )
    }

}
Run Code Online (Sandbox Code Playgroud)

展示:

  • 这应该被接受为答案。 (4认同)

Con*_*lon 23

编辑:使用 .frame 通过简单(更好)的方法更新答案

只需使用框架修改器即可!

struct Expand: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Title")
                .font(.title)
            
            Text("Content")
                .lineLimit(nil)
                .font(.body)
        }
        .frame(maxWidth:.infinity,maxHeight:.infinity,alignment:.topLeading)
        .background(Color.red)
    }
}
Run Code Online (Sandbox Code Playgroud)

注意 - 你甚至不需要 VStack 中的垫片!

注意2 - 如果你不想要顶部和底部的白色,那么在后台使用:

Color.red.edgesIgnoringSafeArea(.all)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 该问题没有要求全屏,而是要求全宽。如果您想超出安全区域,请使用 。边缘忽略安全区域 (2认同)

Jak*_*ake 16

有一个更好的方法!

VStack填充其父对象的宽度,您可以使用GeometryReader并设置边框。(.relativeWidth(1.0)应该可以,但是现在看来不行)

struct ContentView : View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
                Text("test")
            }
                .frame(width: geometry.size.width,
                       height: nil,
                       alignment: .topLeading)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要设置VStack实际屏幕的宽度,可以UIScreen.main.bounds.width在设置框架时使用GeometryReader,而不是使用,但是我想您可能希望使用父视图的宽度。

另外,这种方式的好处还在于VStack,如果您在中添加了HStack带有的Spacer(),则不会在其中添加空格(如果您有间距)VStack

更新-没有更好的方法!

签出接受的答案后,我意识到接受的答案实际上不起作用!乍一看似乎可以使用,但是如果您将其更新VStack为绿色背景,则会发现VStack宽度仍然相同。

struct ContentView : View {
    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                Text("Hello World")
                    .font(.title)
                Text("Another")
                    .font(.body)
                Spacer()
                }
                .background(Color.green)
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
                .background(Color.red)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是因为.frame(...)实际上是在视图层次结构中添加另一个视图,并且该视图最终填满了屏幕。但是,VStack仍然没有。

这个问题似乎也与我的回答相同,可以使用与上述相同的方法进行检查(在之前和之后放置不同的背景色.frame(...)。看来实际上加宽的唯一方法VStack是使用间隔符:

struct ContentView : View {
    var body: some View {
        VStack(alignment: .leading) {
            HStack{
                Text("Title")
                    .font(.title)
                Spacer()
            }
            Text("Content")
                .lineLimit(nil)
                .font(.body)
            Spacer()
        }
            .background(Color.green)
    }
}
Run Code Online (Sandbox Code Playgroud)


thi*_*ezn 11

我设法解决这个问题的最简单方法是使用 ZStack + .edgesIgnoringSafeArea(.all)

struct TestView : View {

    var body: some View {
        ZStack() {
            Color.yellow.edgesIgnoringSafeArea(.all)
            VStack {
                Text("Hello World")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Uma*_*han 11

预览图像

方式 1 -> 使用 MaxWidth 和 MaxHeight

import SwiftUI

struct SomeView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(.red)
    }
}

struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView()
    }
}
Run Code Online (Sandbox Code Playgroud)

方式 2 -> 使用主屏幕边界

import SwiftUI

struct SomeView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
        }
        .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height)
        .background(.red)
    }
}

struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView()
    }
}
Run Code Online (Sandbox Code Playgroud)

方式 3 -> 使用几何读取器

import SwiftUI

struct SomeView: View {
    var body: some View {
        GeometryReader { geometryReader in
            VStack {
                Text("Hello, World!")
            }
            .frame(maxWidth: geometryReader.size.width, maxHeight: geometryReader.size.height)
            .background(.red)
        }
    }
}

struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView()
    }
}
Run Code Online (Sandbox Code Playgroud)

方式 4 -> 使用垫片

import SwiftUI

struct SomeView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
            HStack{
                Spacer()
            }
            Spacer()
        }
        .background(.red)
    }
}

struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView()
    }
}
Run Code Online (Sandbox Code Playgroud)


sva*_*all 10

以下是可行且可能更直观的另一种堆叠安排:

struct ContentView: View {
    var body: some View {
        HStack() {
            VStack(alignment: .leading) {
                Text("Hello World")
                    .font(.title)
                Text("Another")
                    .font(.body)
                Spacer()
            }
            Spacer()
        }.background(Color.red)
    }
}
Run Code Online (Sandbox Code Playgroud)

Spacer()如果需要,也可以通过删除来轻松地重新定位内容。

添加/删除垫片以更改位置

  • 不错的选择 喜欢 gif (6认同)

小智 6

用这个

.edgesIgnoringSafeArea(.all)
Run Code Online (Sandbox Code Playgroud)


Kel*_*ves 6

一个好的解决方案并且没有“装置”是被遗忘的 ZStack

ZStack(alignment: .top){
    Color.red
    VStack{
        Text("Hello World").font(.title)
        Text("Another").font(.body)
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明


Hit*_*esh 5

你可以通过使用来做到这一点GeometryReader

几何阅读器

代码:

struct ContentView : View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
               Text("Turtle Rock").frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading).background(Color.red)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你的输出如下:

在此输入图像描述


iel*_*ani 5

另一种选择是将其中一个子视图放在 an 内HStack并在Spacer()其后放置 a :

struct ContentView : View {
    var body: some View {
        VStack(alignment: .leading) {

            HStack {
                Text("Title")
                    .font(.title)
                    .background(Color.yellow)
                Spacer()
            }

            Text("Content")
                .lineLimit(nil)
                .font(.body)
                .background(Color.blue)

            Spacer()
            }

            .background(Color.red)
    }
}
Run Code Online (Sandbox Code Playgroud)

导致 :

VStack 中的 HStack