SwiftUI: Padding inside TextField
Asked Answered
P

8

20

I have a TextField in SwiftUI. When I apply padding to it as

TextField(text, text: $value)
    .padding()

the padding is outside of the tap area of the TextField, i.e. tapping on the padding does not bring the text field into focus.

I would like to be able to focus the TextField even if the user taps on the padding.

Pittsburgh answered 13/2, 2021 at 10:48 Comment(3)
Check if this answer your questionMerete
That's awfully complicated for something so basic. Having to include libraries just to add padding to my TextField properly. Anyway. Thanks @MeretePittsburgh
Does this answer your question? SwiftUI TextField touchable AreaCoil
D
27

You can try this. At least worked for me. Hope that helps someone:

            TextField("", text: $textfieldValueBinding)
                .frame(height: 48)
                .padding(EdgeInsets(top: 0, leading: 6, bottom: 0, trailing: 6))
                .cornerRadius(5)
                .overlay(
                    RoundedRectangle(cornerRadius: 5)
                        .stroke(lineWidth: 1.0)
                )
Diastema answered 13/8, 2021 at 11:22 Comment(3)
This is the cleanest solution to OP's question.Anele
It works visually, but the padding area is not tappable, so it doesn't solve the OP's problem.Extricate
Works for me in SwiftUI4Faxan
A
4

For iOS 15 and above you can use this:

var body: some View {
    TextField("placeholder", text: $text).focusablePadding()
}



extension View {
    
    func focusablePadding(_ edges: Edge.Set = .all, _ size: CGFloat? = nil) -> some View {
        modifier(FocusablePadding(edges, size))
    }
    
}

private struct FocusablePadding : ViewModifier {
    
    private let edges: Edge.Set
    private let size: CGFloat?
    @FocusState private var focused: Bool
    
    init(_ edges: Edge.Set, _ size: CGFloat?) {
        self.edges = edges
        self.size = size
        self.focused = false
    }
    
    func body(content: Content) -> some View {
        content
            .focused($focused)
            .padding(edges, size)
            .contentShape(Rectangle())
            .onTapGesture { focused = true }
    }
    
}
Ator answered 17/2, 2023 at 6:45 Comment(0)
D
1

you can check this. for now i only did with top and bottom padding. you can do the same with the leading and trailing(or with horizontal and vertical). as asked in the question this would do this "I would like to be able to focus the TextField even if the user taps on the padding."

struct ContentView: View {
@State var name = ""
@State var isTextFieldFocused = false
var body: some View {
        ZStack {
            HStack{
                Text(name)
                    .font(.system(size: 50 , weight: .black))
                    .foregroundColor(isTextFieldFocused ? Color.clear : Color.black)
                Spacer()
            }
            TextField(name, text: $name , onEditingChanged: { editingChanged in
                isTextFieldFocused = editingChanged
            }) 
            .font(.system(size: isTextFieldFocused ? 50 :  100 , weight: .black))
            .foregroundColor(isTextFieldFocused ? Color.black  : Color.clear)
            .frame(width: 300, height: isTextFieldFocused ? 50 :  100 , alignment: .center)
                        .padding(.leading, isTextFieldFocused ? 25 : 0  )
                        .padding(.trailing, isTextFieldFocused ? 25 : 0 )
            
            .padding(.top,isTextFieldFocused ? 25 : 0 )
            .padding(.bottom,isTextFieldFocused ? 25 : 0 )
            
        }.frame(width: 300)
        .background(Color.red.opacity(0.2))
}
}
Disarray answered 13/2, 2021 at 16:4 Comment(2)
This does not answer the question. It adds padding if the textfield does change. But the question is how to focus the TextField when the user taps the added padding.Doleful
This is the answer from #56796212. My issue with it is I have to tap twice for the textfield to focus if text has previously been entered.Coil
W
0

Using the textFieldStyle(RoundedBorderTextFieldStyle()) will add a leading padding into the TextField.

TextField("Projekt Name", text: $projectNameText)
                    .frame(width: .none, height: 40)
                    .font(.system(size: 20, weight: .regular))
                    .padding(.top, 40)
                    .padding(.bottom)
                    .padding(.horizontal)
                    .textFieldStyle(RoundedBorderTextFieldStyle())

enter image description here

Withal answered 6/9, 2023 at 9:32 Comment(0)
D
0

In order to give padding inside TextField in SwiftUI, there are two ways:

  1. Custom Padding and Height with no border

    TextField("Expiry Date", text: $tfExpiryDate)
                                .padding(.horizontal, TEXTFIELD_CUSTOM_INSIDE_PADDING)
                                .frame(height: CUSTOM_HEIGHT)
                                .background(.white)
                                .foregroundStyle(.black)
                                .clipShape(RoundedRectangle(cornerRadius: 8))
                                .padding(.horizontal, TEXTFIELD_CUSTOM_OUTSIDE_PADDING)
    

Note: "TEXTFIELD_CUSTOM_INSIDE_PADDING" and "TEXTFIELD_CUSTOM_OUTSIDE_PADDING" are numbers that will be used for padding, to give space inside and outside textfield.

  1. Padding with border and fixed height

    TextField("Expiry Date", text: $tfExpiryDate)
                                .frame(height: 50)
                                .background(.white)
                                .foregroundStyle(.black)
                                .textFieldStyle(RoundedBorderTextFieldStyle())
                                .clipShape(RoundedRectangle(cornerRadius: 8))
    

Note: This will help you to get padding inside but you can't make textField of your own height and without border, in order to get more customised testField use approach 1.

Dermatophyte answered 9/12, 2023 at 20:52 Comment(0)
S
-1

Yes, but you have to create your own TextFieldStyle. Here's an example:

struct CustomTextField: View {
    
    public struct CustomTextFieldStyle : TextFieldStyle {
        public func _body(configuration: TextField<Self._Label>) -> some View {
            configuration
                .font(.largeTitle) // set the inner Text Field Font
                .padding(10) // Set the inner Text Field Padding
                //Give it some style
                .background(
                    RoundedRectangle(cornerRadius: 5)
                        .strokeBorder(Color.primary.opacity(0.5), lineWidth: 3)) 
        }
    }
    @State private var password = ""
    @State private var username = ""
    
    var body: some View {
        VStack {
            TextField("Test", text: $username)
                .textFieldStyle(CustomTextFieldStyle()) // call the CustomTextField
            SecureField("Password", text: $password)
                .textFieldStyle(CustomTextFieldStyle())
        }.padding()
    }
}
Serna answered 25/6, 2021 at 7:25 Comment(1)
This doesn't seem to affect the tap area.Biotope
G
-2
TextField(
    "TextFiled",
    text: $teamNames,
    prompt: Text("Text Field")
        .foregroundColor(.gray)
)
    .padding(5)
    .frame(width: 250, height: 50, alignment: .center)
    .background(
        RoundedRectangle(cornerRadius: 25, style: .continuous)
            .foregroundColor(.white)
            .padding(.horizontal, -30)
    )
Glean answered 17/1, 2022 at 7:46 Comment(2)
Adding a negative padding in the background modifier will do the job.Glean
adding negative padding to the background modifier won't make the padding tappable?Biestings
O
-4

I don't know if you can give padding inside of a TextField, but you can pad it from outside environment and give it a background of a shape with the same color of your TextField background.

Try this;

        TextField("Username", text: $value)
            .background(Color.yellow)
            .padding(50)
            .background(Capsule().fill(Color.white))
Octonary answered 13/2, 2021 at 12:34 Comment(1)
I want to increase the tap area of the TextField. This does not do that right?Pittsburgh

© 2022 - 2024 — McMap. All rights reserved.