KerrM
KerrM

Reputation: 5240

SwiftUI layout inside VStack using ViewModifiers

I have a simple view with two texts. Its body is like this:

VStack {
    Text("One")
    Text("Two")
    Text("Three")
}

this produces a view like:

Existing layout

But what I would like is, using only modifiers to the Text views (i.e. no HStack with Spacers), achieve a layout like:

Desired layout

Is this currently possible? I was hoping making the Texts full width somehow and then just using the text alignment would work but haven't figured it out yet.

Upvotes: 0

Views: 395

Answers (3)

Asperi
Asperi

Reputation: 258443

Well... as there are no any additional conditions or restrictions, with just added two lines of code

Demo in Preview (blue border is just a selection in code)

demo

    VStack {
        Text("One")
            .frame(maxWidth: .infinity, alignment: .leading)
        Text("Two")
        Text("Three")
            .frame(maxWidth: .infinity, alignment: .trailing)
    }

Upvotes: 2

atomoil
atomoil

Reputation: 404

One approach is to just set the frame:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("One")
                .frame(minWidth: 0,
                       maxWidth: .infinity,
                       alignment: .leading)
            Text("Two")
                .frame(minWidth: 0,
                       maxWidth: .infinity,
                       alignment: .center)
            Text("Three")
                .frame(minWidth: 0,
                       maxWidth: .infinity,
                       alignment: .trailing)

        }
    }
}

Upvotes: 1

cbjeukendrup
cbjeukendrup

Reputation: 3446

Yes, this could be possible. You could define a modifier like:

extension View {
    func horizontalAlignment(_ alignment: HorizontalAlignment) -> some View {
        Group {
            if alignment == .leading {
                HStack {
                    self
                    Spacer()
                }
            } else if alignment == .trailing {
                HStack {
                    Spacer()
                    self
                }
            } else {
                self
            }
        }
    }
}

And use it like:

VStack {
    Text("One")
        .horizontalAlignment(.leading)
    Text("Two")
        .horizontalAlignment(.center)
    Text("Three")
        .horizontalAlignment(.trailing)
}

Of course, multiple approaches are possible.

Upvotes: 1

Related Questions