When I made my transition from UIKit to SwiftUI one of the first challenges that I faced was how to make a custom text field. Text fields are one of the most common components in every app and there'll be times when the default UI won't be enough for us. Very often we need to make some customizable text fields with icons in one side, borders, animations, etc. Lucky for us, SwiftUI gives us more flexibility to do that and an easiest way than UIKit.
In this article we’re gonna make a custom text field using SwiftUI instead UIKit.
If we take a look to the final UI we can differentiate three different components:
- The text field
- The icon
- The under line
We can easily achive this with an HStack and a VStack:
So far so good. But every time we want to use this particular design we have to replicate this bunch of code. So, let’s make it a reusable component.
First of all, lets create a struct that is going to hold the TextField configuration, as follow:
We can use it like this:
That’s much better. But what happen if we want to take a step further and customize the TextView placeholder? Like the font and the color for instance. Unfortunately for us, we don’t have that flexibility (for now) in the TextField component. So we have to put our creativity to fly in order to achieve this.
Given that we can’t customize the TextView placeholder we don't an alternative but to make our own placeholder to our UnderlineTextFieldView struct.
We’re almost there but with this approach we still have an issue to solve. We now have our own placeholder, however if you run the code you’re gonna notice that when we start typing something in our text field, the placeholder doesn’t disappear. This is because we are putting a simple text as a placeholder without any spacial setup. We need to make some adjustments so we can manage the state of the text field.
To do this we can add another String property with the @Binding wrapper that’s going to hold the text that the user is typing in our ContentView. Then we can check if that property is empty or not. If it’s empty then we show our custom placeholder and if it isn't we don't.
And that’s it! Now we’ve our own custom UnderlineTextFieldView!
The above implementation is more than enough. We achieved what we wanted in the first place. Though, we can improve the code a little bit.
First of all, I always like to separate the code into variables to make it semantically more readable. Also, we can make the icon image optional. In that way, we can use our TextField with or without any icon.
We now have a nice reusable code. If you want you can improve it by making it reusable for a TextField and a SecureField as well. We just need to change the textField property type for a generic one:
Thanks for reading, I hope you find it helpful =)