28

I just started with swiftui and I am facing issues in ui alignment. The following code creates a space from top of the image

VStack(alignment: .leading) {
        Image(item.imageUrl)
              .resizable()
              .aspectRatio(contentMode: .fit)
              .frame(width: 72, height: 72, alignment: .top).padding(.top,0)
        Text("\(item.name)").font(Font.system(size:12, design: .default))
             .multilineTextAlignment(.center)
             .frame(maxWidth: .infinity).lineLimit(2)    
        }
}

I can see that VStack accepts param alignment , but it's horizontal alignment. What I need is that the Image should stick to the top of its superview. Is there a way to do this without the use of Spacer().

Like in react-native we used to have justifyContent and alignItems for both horizontal and vertical alignment of children.

UPDATE:

The same issue exists for Text too, or any view. E.g. This code places the two text in center of the view

 VStack(alignment: .leading, spacing: 0) {
        Text("line 1")
        Text("line 2")
 }

enter image description here

The param alignment in VStack is for horizontal alignment.

Now to align these texts to top, the only way I can think of is by introducing Spacer() like this:

struct MyCustomView:View {
  var body: some View {
    VStack(alignment: .leading, spacing: 0) {
      Text("line 1")
      Text("line 2")
      Spacer()
    }
 }

This does solves the problem temporarily:

enter image description here

But the spacer will create problem in complex views, lets say another developer wants to add a custom view (line 3 in this case) just below my view, the spacer will create additional space in between

VStack {
     MyCustomView()
     Text("line 3")
 }

enter image description here

Is there a better way that my child views (and subsequent views) inside a VStack remains aligned to top without the spacer?

3
  • VStack tights to content, so I don't think it is alignment issue, at least in provided code. Could you give more code context and show screenshot? I would be better if you provide minimal reproducible example. Commented Dec 18, 2020 at 12:03
  • Above code is fine.. there is no space at the top. Where is the VStack wrapped inside? Commented Dec 18, 2020 at 12:20
  • @Asperi Updated my question, can you please check Commented Dec 18, 2020 at 12:39

4 Answers 4

35

You can try using .frame() modifier to make the VStack() take full size in it superview. In frame you can align your content topLeading

var body: some View {
    VStack(alignment: .leading, spacing: 0) {
        Text("line 1")
        Text("line 2")
    }
    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
    .border(Color.red)
}

No Spacer needed for that solution

Sign up to request clarification or add additional context in comments.

3 Comments

They want to align sub-views in center.
@mahan Line1 and line2 should be centered? But still at the top right?
@davidev thanks man, the alignment param here is of type 'Alignment' (instead of HorizontalAlignment as in the case of VStack) which accept value for both horizontal and vertical alignment, eg. .top, .center, .topLeading etc.
14

This works too.

 VStack {

          Text("line 1")
          Text("line 2")

    }.frame(maxWidth: .infinity, // Full Screen Width
            maxHeight: .infinity, // Full Screen Height
            alignment: .topLeading) // Align To top

2 Comments

This worked the best for me
It didn't work for me without set the minWidth: 0 and minHeight: 0 params
6

SwiftUI views are cheap. Use another VStack() with Spacer().

    VStack {
        VStack(alignment: .center, spacing: 0) {
          Text("line 1")
          Text("line 2")
          // Add your Views here
        }
        Spacer()
    }

1 Comment

Doesn't work for me.
-1
        VStack(spacing: 30) {
        
        Text("Default Alignment in Vstack is Center")
        
        VStack(alignment: .trailing, spacing: 20) {
            Text(".trailing")
                .font(.title)
            Image(systemName: "rectangle.trailinghalf.inset.filled.arrow.trailing")
                .font(.title)
            
            Text("Alignment set by .trailing")
            
        }.padding()
            .background(RoundedRectangle(cornerRadius: 10).foregroundColor(.yellow))
        
        VStack(alignment: .leading, spacing: 20) {
            Text(".leading")
                .font(.title)
            
            Image(systemName: "rectangle.leadinghalf.inset.filled.arrow.leading")
                .font(.title)
            
            Text("Alignment set by .leading")
            
        }.padding()
            .background(RoundedRectangle(cornerRadius: 10).foregroundColor(.yellow))
        
    }

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.