Home > Mobile >  I am unable to use a spacer to push a text view to the top of my swift ui VStack view, when adding U
I am unable to use a spacer to push a text view to the top of my swift ui VStack view, when adding U

Time:12-31

I have got a piece of code below but the issue is the text field is positioned in the middle of the view and when I add spacers below to push the textfield to the top of the view, it doesn't get pushed the textfield to the top of the view but rather it only moves when i specify the minLength of the spacer but we know this isnt the right approach because different phones have different dimensions. so can someone provide a proper fix to this or spot what is hindering spacer() from working

import SwiftUI

struct FocusedTextField: UIViewRepresentable {
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: FocusedTextField

        init(_ parent: FocusedTextField) {
            self.parent = parent
        }

        func textFieldDidEndEditing(_ textField: UITextField) {
            parent.text = textField.text ?? ""
        }
    }

    @Binding var text: String
    @Binding var isFocused: Bool

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: UIViewRepresentableContext<FocusedTextField>) -> UITextField {
        let textField = UITextField(frame: .zero)
        textField.delegate = context.coordinator
        textField.textColor = .black
        textField.placeholder = "Enter some text"
        return textField
    }

    func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<FocusedTextField>) {
        uiView.text = text
        if isFocused && !uiView.isFirstResponder {
            uiView.becomeFirstResponder()
        }
    }
}

struct testList: View {
    @State private var text: String = ""
    @State private var isFocused: Bool = false

    var body: some View {
        VStack{
            
            FocusedTextField(text: $text, isFocused: $isFocused)
            
        }
        .onAppear {
            self.text = ""
            self.isFocused = true
        }
        .padding()
    }
}


struct textList_Previews: PreviewProvider {
    static var previews: some View {
        testList()
    }
}

CodePudding user response:

For vertical wrap you need to make add some code in makeUIView:

textField.setContentHuggingPriority(.required, for: .vertical)

and add spacer() in testList()

Try below code:

struct FocusedTextField: UIViewRepresentable {
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: FocusedTextField
        
        init(_ parent: FocusedTextField) {
            self.parent = parent
        }
        
        func textFieldDidEndEditing(_ textField: UITextField) {
            parent.text = textField.text ?? ""
        }
    }
    
    @Binding var text: String
    @Binding var isFocused: Bool
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIView(context: UIViewRepresentableContext<FocusedTextField>) -> UITextField {
        let textField = UITextField(frame: .zero)
        textField.delegate = context.coordinator
        textField.textColor = .black
        textField.placeholder = "Enter some text"
        textField.setContentHuggingPriority(.required, for: .vertical)   //<---------------here
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<FocusedTextField>) {
        uiView.text = text
        if isFocused && !uiView.isFirstResponder {
            uiView.becomeFirstResponder()
        }
    }
}

struct testList: View {
    @State private var text: String = ""
    @State private var isFocused: Bool = false
    
    var body: some View {
        VStack{
            
            FocusedTextField(text: $text, isFocused: $isFocused)
            
            Spacer()    //<--------- here
                
            
        }
        .onAppear {
            self.text = ""
            self.isFocused = true
        }
        .padding()
    }
}


struct textList_Previews: PreviewProvider {
    static var previews: some View {
        testList()
    }
}

CodePudding user response:

The problem is in the FocusedTextField. If you use the TextField from SwiftUI itself, you can easily push it up in the VStack by using Spacer().

struct ContentView: View {
    @State private var text: String = ""
    
    var body: some View {
        
        VStack{
            TextField("Enter some Text", text: $text)
            Spacer()
        }        
        .onAppear {
            self.text = ""
        }
        .padding()
    }
}

I highly recommend you look into the @FocusState property wrapper to implement the focus state. You can read more about it here: https://developer.apple.com/documentation/swiftui/focusstate

  • Related