Customize controls with .NET MAUI using PlatformViewFactory
In this post we will use PlatformViewFactory to customize a control without creating a new handler.
Contextualizing
When I wrote this article about customize controls with handlers, Pedro Jesus replied to my tweet suggesting to reimplement the control using PlatformViewFactory.
PlatformViewFactory
It is a static property of ViewHandler that allows to return any implementation of ViewHandler or even the native control itself.
To register it should be added in MauiProgram.cs (or anywhere before Entry handlers will be created in the app).
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
EntryImageHandler.Register();
return builder.Build();
}
}
Implementation
The difference using PlatformViewFactory is instead of creating a custom handler, the function receives the default EntryHandler allowing us to customize the native control as needed.
Android implementation
public static class EntryImageHandler
{
public static void Register()
{
EntryHandler.PlatformViewFactory = (handler) =>
{
var editText = new AppCompatEditText(handler.Context);
if (handler.VirtualView is not ImageEntry)
return editText;
var element = handler.VirtualView as ImageEntry;
if (!string.IsNullOrEmpty(element.Image))
{
switch (element.ImageAlignment)
{
case ImageAlignment.Left:
editText.SetCompoundDrawablesWithIntrinsicBounds(GetDrawable(element.Image, handler.Context, element), null, null, null);
break;
case ImageAlignment.Right:
editText.SetCompoundDrawablesWithIntrinsicBounds(null, null, GetDrawable(element.Image, handler.Context, element), null);
break;
}
}
editText.CompoundDrawablePadding = 25;
editText.Background.SetColorFilter(Colors.White.ToAndroid(), PorterDuff.Mode.SrcAtop);
return editText;
};
}
}
iOS implementation
public static class EntryImageHandler
{
public static void Register()
{
EntryHandler.PlatformViewFactory = (handler) =>
{
var textField = new MauiTextField();
if (handler.VirtualView is not ImageEntry)
return textField;
var element = handler.VirtualView as ImageEntry;
if (!string.IsNullOrEmpty(element.Image))
{
switch (element.ImageAlignment)
{
case ImageAlignment.Left:
textField.LeftViewMode = UITextFieldViewMode.Always;
textField.LeftView = GetImageView(element.Image, element.ImageHeight, element.ImageWidth);
break;
case ImageAlignment.Right:
textField.RightViewMode = UITextFieldViewMode.Always;
textField.RightView = GetImageView(element.Image, element.ImageHeight, element.ImageWidth);
break;
}
}
textField.BorderStyle = UITextBorderStyle.Line;
textField.Layer.MasksToBounds = true;
return textField;
};
}
}
Wrapping Up
You can find the full code on my GitHub.
Subscribe to my newsletter
Read articles from Jhonatan Oliveira directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jhonatan Oliveira
Jhonatan Oliveira
I am an enthusiastic software developer focusing on C#, .NET, Asp.NET, Azure and Angular.