Copied RSS Feed

Xamarin

How to Create Custom Renderers for a Control in Xamarin.Forms

Xamarin.Forms uses a common API to render cross-platform mobile UIs. Therefore, the components can be rendered differently on each platform, using a renderer class. This renderer class creates a native control and translates the properties of the Xamarin.Forms control to it.

Custom renderers are used to ensure a consistency of appearance in elements across platforms for Xamarin controls like style, background color, text format, and so on.

Xamarin.Forms uses abstractions to define these elements. Then, it transforms each abstraction, offering an implementation and mechanism to each platform.

In this article, I will explain how to customize the TimePicker control with a Placeholder property to display text, since the Xamarin.Forms control does not come with this customization property.

Luckily, the native controls of Android and iOS do have this property. Therefore, we only have to extend the existing TimePicker control and create a renderer for each platform.

Let’s get started!

Extending the existing TimePicker

We will start by creating a control that inherits the Xamarin.Forms TimePicker. Then, we’ll add the desired new Placeholder property. For this, we must first create a new folder called Controls and a class named CRTimePicker inside it.

Refer to the following code.

using Xamarin.Forms;

namespace TImePicker_Render.Controls
{
    public class CRTimePicker : TimePicker
    {
        public static readonly BindableProperty EnterTextProperty =
            BindableProperty.Create(propertyName: nameof(Placeholder), returnType: typeof(string), declaringType: typeof(TimePicker), defaultValue: default(string));

        public string Placeholder { get; set; }
    }
}

The TimePicker control will be added in the view where we want to display it. For didactic reasons, I will implement it in the following way in my MainPage file.

<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:controls="clr-namespace:TImePicker_Render.Controls"
             mc:Ignorable="d" x:Class="TImePicker_Render.MainPage">

    <StackLayout VerticalOptions="Center">
       
        <Label Text="TimePicker with Placeholder"
               Margin="10,0"/>
                     
            <controls:CRTimePicker Placeholder="Hora de Inicio"
                                   Visual="Material"/>
    </StackLayout>

</ContentPage>

Now, we must create the renderer on each platform. In this example, we will be using the Visual Material, and therefore we have to inherit the renderer from the MaterialTimePickerRenderer class.

Android

 First, we will create the renderer for Android. In Android, the TextInputLayout native control has a Hint property, which does exactly the work of a placeholder. Therefore, we have to create this renderer in the Android project in order to have access to the native controls.

Refer to the following code.

using Android.OS;
using Android.App;
using Xamarin.Forms;
using Android.Content;
using Android.Text.Format;
using TImePicker_Render.Controls;
using Xamarin.Forms.Material.Android;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CRTimePicker), typeof(TImePicker_Render.Droid.TimePickerRenderer), new[] {
typeof(VisualMarker.MaterialVisual) })]
namespace TImePicker_Render.Droid
{
    class TimePickerRenderer : MaterialTimePickerRenderer
    {
        public TimePickerRenderer(Context context) : base(context) { }

        protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
        {
            base.OnElementChanged(e);

            //Placeholder
            if (Element is Controls.CRTimePicker picker && !string.IsNullOrWhiteSpace(picker.Placeholder))
            {
                Control.HintEnabled = true;
                Control.Hint = picker.Placeholder;
            }
        }
 
        bool Is24HourView
        {
            get => (DateFormat.Is24HourFormat(Context) && Element.Format == (string) TimePicker.FormatProperty.DefaultValue)
                   || Element.Format == "HH:MM";
        }

        protected override TimePickerDialog CreateTimePickerDialog(int hours, int minutes)
        {
            var dialog = new TimePickerDialog(Context, Resource.Style.AppCompatDialogStyle, this, hours, minutes, Is24HourView);

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                dialog.CancelEvent += (s, e) => Element.Unfocus();
            return dialog;
        }
    }
}

Note: Remember that, to work with Visual Material, we must add the NuGet package Xamarin.Forms.Visual.Material to the Android and iOS projects.

More Information: Beautiful Design for Android & iOS

iOS

Now, we have to implement the renderer for the iOS platform. In this case, the control must be inherited from the IMaterialEntryRenderer interface, which has the properties to display the placeholder.

As with Android, this renderer will also have to be created in the iOS project.

Refer to the following code.

using Xamarin.Forms;
using TImePicker_Render.Controls;
using Xamarin.Forms.Material.iOS;

[assembly: ExportRenderer(typeof(CRTimePicker), typeof(TImePicker_Render.iOS.TimePickerRenderer), new[] {
typeof(VisualMarker.MaterialVisual) })]
namespace TImePicker_Render.iOS
{
    class TimePickerRenderer : MaterialTimePickerRenderer, IMaterialEntryRenderer
    {
        public TimePickerRenderer() : base() { }

        string IMaterialEntryRenderer.Placeholder
        {
            get
            {
                if (Element is CRTimePicker picker && !string.IsNullOrWhiteSpace(picker.Placeholder))
                return picker.Placeholder;
                return string.Empty;
            }            
        }
    }
}

Once the renderers are created, we can test and verify the result, where we can see the TimePicker with the Placeholder, both in iOS 13.5 and Android 10.0, like in the following screenshot.

Result

iOS 13.5
Android 10.0

The complete code for this example can be found in this GitHub repository: TimePicker_Render

Conclusion

I hope you understood the concepts of creating custom renderers for the TimePicker control with a placeholder in Xamarin.Forms. Like this, you can also customize renderers for other controls in Xamarin.Forms. So, try them out and leave your feedback in the comments section below!

Syncfusion’s Xamarin suite offers over 150 UI controls, from basic editors to powerful, advanced controls like DataGrid, Charts, ListView, and RTE. Use them to boost your productivity!

You can reach us through our support forumDirect-Trac, or feedback portal. We are here to help you!

Happy coding! Until next time!

Meet the Author

Vicente Gerardo Guzmán Lucio

Vicente Guzmán has more than 8 years of experience in the professional field, focusing on the development of mobile apps.
He was acknowledged as MVP of Microsoft in the category of Windows Development. Currently he works as a Mobile Project Leader, centered in the development with Xamarin technology.