Make a VStack fill the width of the screen in Swif

2020-02-05 05:48发布

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 interace:

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?

11条回答
干净又极端
2楼-- · 2020-02-05 06:18

I know this will not work for everyone, but I thought it interesting that just adding a Divider solves for this.

struct DividerTest: View {
var body: some View {
    VStack(alignment: .leading) {
        Text("Foo")
        Text("Bar")
        Divider()
    }.background(Color.red)
  }
}
查看更多
冷血范
3楼-- · 2020-02-05 06:20

This is a useful bit of code:

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

Compare the results with and without the .expandable() modifier:

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

-

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

enter image description here

查看更多
唯我独甜
4楼-- · 2020-02-05 06:21

Try using the .frame modifier with the following options:

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

查看更多
你好瞎i
5楼-- · 2020-02-05 06:24

An alternative stacking arrangement which works and is perhaps a bit more intuitive is the following:

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

The content can also easily be re-positioned by removing the Spacer()'s if necessary.

adding/removing Spacers to change position

查看更多
干净又极端
6楼-- · 2020-02-05 06:24

This is what worked for me (ScrollView (optional) so more content can be added if needed, plus centered content):

import SwiftUI

struct SomeView: View {
    var body: some View {
        GeometryReader { geometry in
            ScrollView(Axis.Set.horizontal) {
                HStack(alignment: .center) {
                    ForEach(0..<8) { _ in
                        Text("                                                                    
查看更多
劫难
7楼-- · 2020-02-05 06:25

One more alternative is to place one of the subviews inside of an HStack and place a Spacer() after it:

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

resulting in :

HStack inside a VStack

查看更多
登录 后发表回答