0

I display simple view with two text fields inside a vStack/HStack combination. It leaves a huge gap at the top as shown on the attached image. I tried vStack, it has .leading and .trailing which justifies left or right. How can set specific spacing at the top? code:

struct PlanDetailView:  View {
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.dismiss) var dismiss
@Environment(\.presentationMode) var presentationMode

@Binding  var chosenPlan: ProviderApiCaller.ProviderData


@State var state: String?
@State var zip: String?

func onAdd(plan: ProviderApiCaller.ProviderData ) {
    
}
var body: some View {
    NavigationView {
        VStack {
            HStack {
                Text(chosenPlan.name!)
            }
            HStack {
                Text(chosenPlan.plans.first!.planUrl)
            }
        }
    }
    .navigationTitle("Plan Details")
    .toolbar {
        // Back button
        ToolbarItem(placement: .navigationBarLeading) {
            Button(action: {  presentationMode.wrappedValue.dismiss() }, label: {
                HStack(spacing: 2) {
                    Image(systemName: "chevron.backward")
                        .foregroundColor(.black)
                    
                    Button("Back", action: {
                        self.presentationMode.wrappedValue.dismiss()
                    } )
                    .foregroundColor(.black)
                }
            })
        }
        ToolbarItem(placement: .confirmationAction) {
           // Button("Save", action: { Task { try? await rI?(nameInput, phoneInput) } })
            Button("Save", action: { onAdd(plan: chosenPlan)
               
            } )
            
                .foregroundColor(.blue)
                
        }
    }
    .navigationViewStyle(StackNavigationViewStyle())
    .navigationBarBackButtonHidden(true)
}
    

view}

Ken White
  • 123,280
  • 14
  • 225
  • 444
vrao
  • 545
  • 2
  • 12
  • 33

1 Answers1

1

For this simple view, you only need to add a Spacer() in as the last view in the VStack:

var body: some View {
    NavigationView {
        VStack {
            HStack {
                Text(chosenPlan.name!)
            }
            HStack {
                Text(chosenPlan.plans.first!.planUrl)
            }
            // Place a Spacer() here to push the view to the top
            Spacer()
        }
    }
    ...
}

Also, you will find that the way you have this view set up, you do not need the HStacks, so this renders the same as above:

var body: some View {
    NavigationView {
        VStack {
            Text(chosenPlan.name!)
            Text(chosenPlan.plans.first!.planUrl)
            // Place a Spacer() here to push the view to the top
            Spacer()
        }
    }
    ...
}

Lastly, you should not be force unwrapping chosenPlan.name or chosenPlan.plans.first. You are telling the os to crash your app if those optionals are nil.

var body: some View {
    NavigationView {
        VStack {
            Text(chosenPlan.name ?? "") // nil-coalescing operator (??)
            Text(chosenPlan.plans.first?.planUrl ?? "") // nil-coalescing operator (??)
            // Place a Spacer() here to push the view to the top
            Spacer()
        }
    }
    ...
}

You can add whatever default set you want after the nil-coalescing operator (??).

edit:

Based on your comment, I have updated my answer. Rather than setting an absolute position, your would be far better off doing something like this:

var body: some View {
    NavigationView {
        VStack {
            // Set a frame on a Spacer(). In SwiftUI it is better to have a
            // view push another view, rather than set an absolute position.
            Spacer()
                .frame(height: 100)

            Text(chosenPlan.name ?? "") // nil-coalescing operator (??)
            Text(chosenPlan.plans.first?.planUrl ?? "") // nil-coalescing operator (??)
            // Place a Spacer() here to push the view to the top
            Spacer()
        }
    }
    ...
}
Yrb
  • 8,103
  • 2
  • 14
  • 44
  • Thanks. It pushes it all the way to the top and does not look pleasing. So I want to position it at fixed location. I tried position VStack at .position(x:20, y:100), The entire text disappears. I tied the same command at the first Hstack, thinking it would envelope everything within, but it truncates the text. Basically .pos does not work the way I expect it to. is there a way I can accurately position each text line using .pos or some other command – vrao Jun 01 '23 at 16:33