Post

How to modify the border of a .NET MAUI Entry on iOS and MacCatalyst

In my recent side project, TwistReader, I needed to modify the Border of an Entry to match my application’s primary color. The .NET MAUI Entry does not provide a direct way to change the color of the border, however. Luckily, it isn’t that difficult to change the color of the border, nonetheless.

Modifying the mapping of the native control

The .NET MAUI Entry renders to a native UITextField. The logical consequence is that I need to use the Mapper of the Entry control to modify the Border of the underlying native control. This is pretty easy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 internal void ModifyUiTextField()
{
    Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(ModifyUiTextField), (handler, view) =>
    {
        handler.PlatformView.BorderStyle = UITextBorderStyle.None;
        
        handler.PlatformView.Layer.BorderColor = UIColor.SystemGray3.CGColor;
        handler.PlatformView.Layer.BorderWidth = 2.0f;
        handler.PlatformView.Layer.MasksToBounds = true;
        handler.PlatformView.Layer.CornerRadius = 8.0f;
        
        handler.PlatformView.EditingDidBegin += (sender, args) =>
        {
            handler.PlatformView.Layer.BorderColor = ((Color)App.Current.Resources["Primary"]).ToCGColor();
        };

        handler.PlatformView.EditingDidEnd += (sender, args) =>
        {
            handler.PlatformView.Layer.BorderColor = UIColor.SystemGray3.CGColor;
        };
    });
}

Let’s break that down. I call the ModifyUiTextField() method in the constructor of the containing page (as this is the only occurrence of an Entry so far). We could also add this in App.xaml.cs, which would modify all Entry instances throughout the app.

First, we need to deactivate the built-in Border by setting the UITextField.BorderStyle property to UITextBorderStyle.None;

The next step is to use to change the Border related properties of the UITextField‘s <a href="https://developer.apple.com/documentation/quartzcore/calayer?language=objc">CALayer</a>. The default color is SystemGray3, so if we do not have focus (aka not being the first responder) on the control, this will be the default. Setting MasksToBounds to true makes sure everything rests within the control. Finally, I added some nice rounded corners to the Border by setting the CornerRadius.

By handling the native control’s EditingDidBegin and EditingDidEnd events, we are able to switch between the default color and our application’s primary (or whatever) color. This will look like this:

.NET MAUI entry in focused and unfocused state without padding for the placeholder and input text As you can see, the coloring part is now working as intended. But the text (both placeholder and input text), is not aligned well within the control.

Fixing text alignment

The text alignment of the UITextField is also a common problem for native iOS programming for years. Because of this, there are tons of posts on StackOverflow and the rest of the web explaining how to fix this. Almost all of them point to a simple solution – adding a padding view to move the text into place. This is my implementation of it:

1
2
3
4
5
 var paddingView = new UIView(new CGRect(0, 0, 10, handler.PlatformView.Frame.Height));
handler.PlatformView.LeftView = paddingView;
handler.PlatformView.LeftViewMode = UITextFieldViewMode.Always;
handler.PlatformView.RightView = paddingView;
handler.PlatformView.RightViewMode = UITextFieldViewMode.Always;

Inserting this code after setting the Border properties will add a nice margin to both sides of the Entry and makes the control finally look like we wanted:

.NET MAUI entry in focused and unfocused state with padding for the placeholder and input text

Conclusion

Even with .NET MAUI, we sometimes need to touch the underlying native implementation to modify the controls to our needs. The handler architecture of .NET MAUI makes this pretty easy. With a bit of a good search-foo, we can easily find the native solutions and adapt them in our apps. If you want to make the code above reusable, just create your own custom version of an Entry as described in the docs.

As always, I hope this post will be helpful for some of you.

Until the next post, happy coding!


Title image generated with AI

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.