I recently began dabbling in mobile development; specifically, with Xamarin iOS. It’s been a great experience and I’m making major progress on a side project that I hope will be in decent enough shape to release to the public in the coming months.
If you’re like me, you’re not an expert in UI/UX or design — nor do you want to spend endless hours pretending to be— but you do appreciate it when your app doesn’t look like a total mess while prototyping and getting functionality laid out.
For this, it’s important to have readily available tools to allow for rapid prototyping while maintaining a clean appearance. I will be giving a tutorial on how to implement one such tool in this post.
I guess this is where I introduce you to my flat and minimal validation text fields:
If this looks like something you might find useful, then keep reading. I’m going to jump straight into it!
I would just like to point out that for this tutorial I am assuming some previous knowledge of Visual Studio and Xamarin iOS. However, if you are completely new and I glance over anything too quickly, I’d be happy to answer questions!
You can reference the complete source code here.
Let’s start by creating a new single view application.
Once the project loads, open up your storyboard and add a new
UITextField and do the following:
- Give it an identity name (I used NameTextField)
- Resize it to 275px by 30px
- Remove the border style
- Remove the initial text
- Add placeholder text
- Optional: Add constraints
You should end up with something similar to this:
Coloring UIView Borders
Now for some actual code. The first thing we will do is add functionality for coloring the borders of a
UIView. We will accomplish this via an extension method.
Add a new class file to your project called UIViewExtensions.cs. The initial code looks as follows:
public static class UIViewExtensions
In order to extend
UIView we must add our methods to a
public static void ColorBorders
The extension method for coloring the borders of a
this UIView view: The
UIViewthat this extension method operates on
CGColor color: The border color
nfloat width: The border width
enumspecifying which borders to color (see below for more info)
public enum BorderDirection
An enum used to declare which borders of the
UIView should be colored. Can be of value Top, Bottom, Left, Right or All.
Next, add the following
static readonly variables to the UIViewExtensions class.
Here we add a prefix which will be used for naming border sub-layers added to our
UIView for easy retrieval in the future and an array of all border directions (excluding
Now we can add some logic to
We’ll start by looping through
ALL_BORDERS and check each possible border against the
direction parameter passed to our method.
If the border should be colored, we use the
COLOR_BORDERS_EXT prefix from earlier to create a name for the border layer. The final result will be something like color-borders-ext.Top.
Next, we attempt to find a previously added sub-layer with the same name. If one is found, we can reuse it. If no such sub-layer exists, we instantiate a new
CALayer and add it to the
We must determine the frame of the layer we are coloring. To do this we will add a local function to
Use of a local function is not necessary by any means but I think it makes sense for this use case.
I would like to point out that these
CGRect definitions are created with maintaining the UIView’s size in mind. If you wish, you can alter these frames to extend outward past the UIView’s bounds. You just need to ensure that you set:
view.Layer.MasksToBounds = false;
To finish our border coloring functionality, all we need to do is assign our sublayer’s Frame, Name, BorderWidth and BorderColor properties.
Now we can test that our new extension method works!
Open your initial view controller’s backing class and override the
ViewDidLoad() method. Inside the method, call
ColorBorders() on our NameTextField.
Now, run your app and see what happens!
Bordered Text Field
Before we get to the validation text fields, let’s take our border coloring functionality one step further and create a new class called
Create a new class file named BorderedTextField.cs and populate it like so:
This gives us a clean way to define and color our text fields which will take some unnecessary bulk out of the validation text field class.
Go back to the view controller backing class and replace:
Once you run your app, the text field should look exactly the same as it did earlier.
Great, onto the validation text fields!
Validation Text Fields
Let’s create a new class file called ValidationTextField.cs. Like our extension method, we will also add an
enum to this file for tracking the field’s validation state.
The constructor accepts an instance of
BorderedTextField as its only parameter. We will add more to the constructor in a minute but for now we hold onto the
BorderedTextField and set all state colors to the initial border color of the provided text field.
We also created an
enum for tracking the field’s validation state. The field can have a state of Neutral, Valid or Error.
Next, we will add a
UILabel with the purpose of outputting any validation errors.
To do this we create a
private UILabel class variable that is instantiated in the constructor and added to the text field’s superview (parent view).
Okay so there is a good amount added here:
We added a
UILabel for displaying validation errors as well as a public property that adds some optional customization of the error font.
The font is initially set to mimic the text field font in the constructor. Since it is likely we don’t want them to be exactly the same size, or even the same font family, we can use this property to update the error label’s font. It will set the font and resize the label as needed.
If you used constraints as I did, the final size of frames will not be correct when overriding the view controller’s
ViewDidLoad() method. To remedy this, we added a method call
Reframe() that can handle resizing the error label’s frame once all subviews have been laid out. We will call it from the view controller’s backing class later on.
In the constructor we find the text field’s superview. In our case, this is the view controller containing the text field. We instantiate the error label, set the text alignment to Center (feel free to change this as you’d like) and set the ErrorFont property mentioned above to the font of the text field. Once this is all complete, the error label is added to the superview as a subview.
Text Field Editing
Aside from validation state colors, we will add a color specifically for when the text field is being edited. To do so, we will add a new
CGColor property and events for when editing begins and ends.
Next, we will start implementing how we will handle validation. We will use events that trigger either error or neutral states. Anything else will be considered success. To do so, we will add a new internal class called Trigger, a private list of triggers for both the error and neutral states and a public methods for adding new triggers.
Important Note on Trigger Functions
Because these functions are running asynchronously, we cannot use any UIKit related properties or methods without invoking them on the main thread. I am not going to dive too deep into this now but you can read more on it here.
Essentially, our trigger functions cannot reference other Views, Labels, Buttons, etc.
An example of this would be if you want to compare a password field to a confirmation password field during sign up.
For now, let’s keep our trigger functions simple and I will cover a work around in a second post if anyone is interested.
Now that we have our triggers implemented we are getting close!
Let’s add our validation logic to
ValidationTextField. It will check for a match against neutral triggers first, then error triggers and everything else will be considered a valid state.
Note that the text field’s current text value is pulled before the tasks are ran. This is because of what I mentioned above. If we were to attempt to read the text in an asynchronous thread, we would get an exception.
Okay. Now we want to call this from a new
public async method called
Next, we will use the trigger returned to update the validation field.
Last but not least, let’s make sure we call
Validate() when the field has finished editing!
Alright, let’s go back to our view controller’s backing class to test it all out!
I will be going through each piece of code here, but first, there is one line that I added for the purpose of this tutorial:
It calls the following extension method in our UIViewExtensions class:
This method enables functionality that ends editing of whichever view is currently focused when the view controller is tapped. This isn’t necessary in all apps (nor is it always a good idea because it may interfere with other user touch interactions) but for our testing we have no other views, buttons or text fields to tap and complete editing.
The last thing for us to do is build and run our app and test the validation!
If all went well, it should result in something similar to the following:
I really hope some of you found this useful. If you have any questions or feedback I would love to hear so please reach out. Otherwise, thank you for reading!
Once again, you can reference the complete source code here.