Twitter Facebook RSS Feed

miércoles, 11 de diciembre de 2019 a las 11:50hs por Gustavo Cantero (The Wolf)

Uno de los problemas con los que nos topamos al desarrollar un formulario con Xamarin Forms es que, a diferencia del control Entry, no existe la propiedad Placeholder en el DatePicker para identificar qué se está ingresando en ese campo.
Por suerte los controles nativos de Android e iOS tienen opciones para esto, por lo cual, sólo tuvimos que hacer un control que herede del DatePicker original y crear un renderer para cada plataforma, para implementar esta propiedad.

Para comenzar, creamos el control que herede del DatePicker de Xamarin Forms, para agregar la nueva propiedad:

using Xamarin.Forms;

namespace MiProyecto.Controls
{
    public class MyDatePicker : Xamarin.Forms.DatePicker
    {
        public static readonly BindableProperty EnterTextProperty =
            BindableProperty.Create(propertyName: nameof(Placeholder), returnType: typeof(string), declaringType: typeof(MyDatePicker), defaultValue: default(string));

        public string Placeholder { get; set; }
    }
}

Este control lo podemos utilizar de la siguiente forma:

<?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:MiProyecto.Controls"
             mc:Ignorable="d">
    <controls:DatePicker Placeholder="Fecha de nacimiento"
                         Visual="Material"
                         Format="D"
                         VerticalOptions="Center" />
</ContentPage>

Ahora deberemos crear el Renderer en cada plataforma. Nótese que nosotros utilizamos el Visual Material, con lo cual, deberemos heredar de la clase MaterialDatePickerRenderer.

Android

Primero crearemos el renderer para Android, cuyo control nativo, el TextInputLayout, tiene la propiedad Hint para que hace lo mismo que el Placeholder.
Este renderer tendremos que crearlo en el proyecto de Android, para poder tener acceso a los controles nativos.

using Android.App;
using Android.Content;
using Xamarin.Forms;
using Xamarin.Forms.Material.Android;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(MiProyecto.Controls.MyDatePicker), typeof(MiProyecto.Droid.Renderer.DatePickerRenderer), new[] { typeof(VisualMarker.MaterialVisual) })]
namespace MiProyecto.Droid.Renderer
{
    class DatePickerRenderer : MaterialDatePickerRenderer
    {
        public DatePickerRenderer(Context context) : base(context) { }

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

            //Placeholder
            if (Element is Controls.MyDatePicker picker && !string.IsNullOrWhiteSpace(picker.Placeholder))
            {
                Control.HintEnabled = true;
                Control.Hint = picker.Placeholder;
            }
        }
    }
}

iOS

Ahora tenemos que hacer lo mismo, pero para iOS. En este caso, el control también debe heredar de la interfaz IMaterialEntryRenderer, que tiene las propiedades para mostrar el placeholder, pero que el control DatePicker de Xamarin blanquea.
Al igual que con Android, este renderer tendremos que crearlo en el proyecto de iOS.

using Xamarin.Forms;
using Xamarin.Forms.Material.iOS;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(MiProyecto.Controls.MyDatePicker), typeof(MiProyecto.iOS.Renderer.DatePickerRenderer), new[] { typeof(VisualMarker.MaterialVisual) })]
namespace MiProyecto.iOS.Renderer
{
    class DatePickerRenderer : MaterialDatePickerRenderer, IMaterialEntryRenderer
    {
        public DatePickerRenderer() : base() { }

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

Con estos renderers, veremos el DatePicker en iOS 13.3 y Android 10.0 como se muestra a continuación.

Espero les sirva este artículo.
¡Suerte!

0 comentarios »

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.