swiftuialignmentvstackhstack

Center HStack content excluding content in VStack


I have a pretty basic view with an HStack, that has an Image, VStack, Text, and another Image in it. What I would like for is the speedometer image, the ProgressView (which is in the VStack), the "75" text, and the chevron image to be centered horizontally. Maybe there is a better way to structure this, or some modifier I can apply that I'm not aware of. Again the goal is to have a horizontal row of content that is the Image, ProgressView, Text and an Image centered horizontally with the "Hello" text leading aligned to the ProgressView. Here is a screenshot of its current state and the code.

Default font

struct ContentView: View {
    var body: some View {
        HStack(alignment: .lastTextBaseline) {
            Image(systemName: "speedometer")
            VStack(alignment: .leading) {
                Text("Hello")
                ProgressView(value: 50, total: 100)
                    .progressViewStyle(.linear)
            }
            Text("75")
            Image(systemName: "chevron.forward")
        }
        .padding()
    }
}

This is what I want the alignment to look like. What is missing from this screenshot is I want the text "Hello" to be above the ProgressView, and leading aligned:

HStack


Solution

  • There would be a number of ways to achieve this layout. Techniques at your disposal include:

    Here is a variation that uses a VStack containing two HStack. If the size of the speedometer image would be known then padding could be used to reserve this space. Since it is not known, a hidden version of the image is used instead:

    VStack(alignment: .leading, spacing: 0) {
        HStack {
            Image(systemName: "speedometer")
                .hidden()
            Text("Hello")
        }
        HStack {
            Image(systemName: "speedometer")
            ProgressView(value: 50, total: 100)
                .progressViewStyle(.linear)
            Text("75")
            Image(systemName: "chevron.forward")
        }
    }
    .padding()
    

    Screenshot