给定以下代码:

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

它的结果是这个接口:

我怎样才能使VStack填充屏幕的宽度,即使标签/文本组件不需要全宽度?


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

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

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

  Spacer()
}

产生所需的设计:

有没有更好的办法?


当前回答

这是一段有用的代码:

extension View {
    func expandable () -> some View {
        ZStack {
            Color.clear
            self
        }
    }
}

比较使用. expanded()修饰符和不使用. expanded()修饰符的结果:

Text("hello")
    .background(Color.blue)

-

Text("hello")
    .expandable()
    .background(Color.blue)

其他回答

使用这个

.edgesIgnoringSafeArea(.all)

方法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()
    }
}

方法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()
    }
}

方法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()
    }
}

方法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()
    }
}

这是一段有用的代码:

extension View {
    func expandable () -> some View {
        ZStack {
            Color.clear
            self
        }
    }
}

比较使用. expanded()修饰符和不使用. expanded()修饰符的结果:

Text("hello")
    .background(Color.blue)

-

Text("hello")
    .expandable()
    .background(Color.blue)

编辑:答案更新为使用.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)
    }
}

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

注意2:如果你不想在顶部和底部使用白色,那么在背景中使用:

Color.red.edgesIgnoringSafeArea(.all)

在Swift 5.2和iOS 13.4中,根据你的需要,你可以使用下面的例子之一来对齐你的VStack与顶部领先约束和全尺寸框架。

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


1. 使用frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:)方法

最简单的方法是设置你的VStack的帧的最大宽度和高度,并在帧中传递所需的对齐(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)
    }

}

2. 使用间隔来强制对齐

你可以将你的VStack嵌入到一个完整大小的HStack中,并使用尾部和底部间隔来强制你的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)
    }

}

3.使用ZStack和一个全尺寸的背景视图

这个例子展示了如何将你的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)
            }
        }
    }

}

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)
    }

}

5. 使用overlay(_:alignment:)方法

如果你想在现有的全尺寸视图的顶部对齐你的VStack,你可以使用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
            )
    }

}

显示: