skip to Main Content

I’m trying to create a simple page that has an option to select from a few different options, and then a text field and button that show up after an option has been selected. The logic works great, but unfortunately there’s a great deal of white space between the Form object and the rest of the UI elements – is there a way to change this?

Here is the code:

        VStack {
        Text("What would you like help with?")
            .font(.largeTitle)
            .fontWeight(.bold)
            .multilineTextAlignment(.center)
                    
        Form {
            Picker("Color", selection: $selectedIndex) {
                ForEach(0 ..< arrayOfNames.count) {
                    Text(self.arrayOfNames[$0])
                }
            }
        }
        
        TextField("Enter your question", text: $question)
            .opacity(selectedIndex > 0 ? 1 : 0)
            .textFieldStyle(RoundedBorderTextFieldStyle())
        
        Button(action: {}) {
            Text("Ask")
        }.opacity(selectedIndex > 0 ? 1 : 0)
    

And here is an image which shows the problem:

2

Answers


  1. When you select the Form in your code, you see in the canvas that it takes all the space it can get in the screen and therefor pushes the TextField and the Button to the end of the screen.

    There are two possible options. The first is that you use the Picker as is and don’t put it in a Form. You’ll see that the views will come together. The second possibility is to set the frame height of the Form with the height, that you want to give it and then the screen looks better.

    VStack {
        Text("What would you like help with?")
            .font(.largeTitle)
            .fontWeight(.bold)
            .multilineTextAlignment(.center)
    
        Form {
            Picker("Color", selection: $selectedIndex) {
                ForEach(0 ..< arrayOfNames.count) {
                    Text(self.arrayOfNames[$0])
                }
            }
        }
        .frame(height: 100, alignment: .center)
            
        TextField("Enter your question", text: $question)
            .opacity(selectedIndex > 0 ? 1 : 0)
            .textFieldStyle(RoundedBorderTextFieldStyle())
    
        Button(action: {}) {
            Text("Ask")
        }
        .opacity(selectedIndex > 0 ? 1 : 0)
    }
    
    Login or Signup to reply.
  2. This answer is very similar to my answer here.

    My answer uses SwiftUI-Introspect, so you can get the content height and don’t have to guess the correct height. You can be sure this will adapt to various things like screen orientation, font size, etc.

    Form is very greedy in height – you need to limit it in some way. What I’m doing is getting the Form content’s real height, and then using that to restrict the Form height.

    Solution

    1. Create a @State variable to contain the content height:
    @State private var contentHeight: CGFloat?
    
    1. Add code to restrict Form height:
    Form {
        /* ... */
    }
    .introspectTableView { tableView in
        contentHeight = tableView.contentSize.height
    }
    .frame(height: contentHeight)
    

    And that’s it!

    Result:

    Result

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search