iosswiftxcodeswiftui

Make a VStack fill the width of the screen in SwiftUI


Given this code:

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

It results in this interface:

preview

How can I make the VStack fill the width of the screen even if the labels/text components don't need the full width?


A trick I've found is to insert an empty HStack in the structure like so:

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

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

  Spacer()
}

Which yields the desired design:

desired output

Is there a better way?


Solution

  • Try using the .frame modifier with the following options:

    .frame(
          minWidth: 0,
          maxWidth: .infinity,
          minHeight: 0,
          maxHeight: .infinity,
          alignment: .topLeading
        )
    
    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)
      }
    }
    

    This is described as being a flexible frame (see the documentation), which will stretch to fill the whole screen, and when it has extra space it will center its contents inside of it.