Personalización de una entrada

El control Entry de Xamarin.Forms permite que se edite una sola línea de texto. En este artículo se muestra cómo crear un representador personalizado para el control Entry, lo que permite que los desarrolladores reemplacen la representación nativa de forma predeterminada con su propia personalización específica de la plataforma.

Todos los controles de Xamarin.Forms tienen un representador que las acompaña para cada plataforma y que crea una instancia de un control nativo. Cuando una aplicación de Xamarin.Forms representa un control Entry, se crea en iOS una instancia de la clase EntryRenderer que, a su vez, crea una instancia de un control UITextField nativo. En la plataforma Android, la clase EntryRenderer crea una instancia de un control EditText. En la Plataforma universal de Windows (UWP), la clase EntryRenderer crea una instancia de un control TextBox. Para obtener más información sobre el representador y las clases de control nativo a las que se asignan los controles de Xamarin.Forms, vea Clases base y controles nativos del representador.

El siguiente diagrama muestra la relación entre el control Entry y los controles nativos correspondientes que lo implementan:

Relación entre el control Entry y los controles nativos de implementación

El proceso de representación puede aprovecharse para implementar las personalizaciones específicas de la plataforma creando un representador personalizado para el control Entry en cada plataforma. Para ello, siga este procedimiento:

  1. Cree un control personalizado de Xamarin.Forms.
  2. Consuma el control personalizado de Xamarin.Forms.
  3. Cree el representador personalizado para el control en cada plataforma.

Ahora se analizará en detalle cada elemento, para implementar un control Entry que tiene un color de fondo diferente en cada plataforma.

Importante

En este artículo se explica cómo crear un representador personalizado simple. Empero, no es necesario crear un representador personalizado para implementar un Entry que tiene un color de fondo diferente en cada plataforma. Esto puede realizarse más fácilmente usando la clase Device o la extensión de marcado OnPlatform, para proporcionar los valores específicos de la plataforma. Para obtener más información, vea Providing Platform-Specific Values (Proporcionar valores específicos de la plataforma) y OnPlatform Markup Extension (Extensión de marcado OnPlatform).

Creación de un control Entry personalizado

Se puede crear un control Entry personalizado mediante la creación de subclases del control Entry, como se muestra en el siguiente ejemplo de código:

public class MyEntry : Entry
{
}

El control MyEntry se crea en el proyecto de biblioteca de .NET Standard y es simplemente un control Entry. La personalización del control se llevará a cabo en el representador personalizado, por lo que no se requiere ninguna implementación adicional en el control MyEntry.

Uso del control personalizado

En XAML puede hacerse referencia al control MyEntry en el proyecto de biblioteca de .NET Standard declarando un espacio de nombres para su ubicación y usando el prefijo del espacio de nombres en el elemento de control. El siguiente ejemplo de código muestra cómo el control personalizado MyEntry puede utilizarse en una página XAML:

<ContentPage ...
    xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
    ...>
    ...
    <local:MyEntry Text="In Shared Code" />
    ...
</ContentPage>

El prefijo de espacio de nombres local puede tener cualquier nombre. Empero, los valores clr-namespace y assembly deben coincidir con los detalles del control personalizado. Una vez que se declara el espacio de nombres, el prefijo se usa para hacer referencia al control personalizado.

El siguiente ejemplo de código muestra cómo el control personalizado MyEntry puede utilizarse en una página C#:

public class MainPage : ContentPage
{
  public MainPage ()
  {
    Content = new StackLayout {
      Children = {
        new Label {
          Text = "Hello, Custom Renderer !",
        },
        new MyEntry {
          Text = "In Shared Code",
        }
      },
      VerticalOptions = LayoutOptions.CenterAndExpand,
      HorizontalOptions = LayoutOptions.CenterAndExpand,
    };
  }
}

Este código crea una instancia de un nuevo objeto ContentPage que mostrará un Label y un control MyEntry centrado tanto vertical como horizontalmente en la página.

Ahora se puede agregar un representador personalizado a cada proyecto de aplicación para personalizar la apariencia del control en cada plataforma.

Creación del representador personalizado en cada plataforma

El proceso de creación de la clase de representador personalizada es el siguiente:

  1. Cree una subclase de la clase EntryRenderer que representa el control nativo.
  2. Invalide el método OnElementChanged que representa el control nativo y escriba lógica para personalizar el control. Se llama a este método cuando se crea el correspondiente control de Xamarin.Forms.
  3. Agregue un atributo ExportRenderer a la clase de representador personalizada para especificar que se usará para representar el control de Xamarin.Forms. Este atributo se usa para registrar al representador personalizado con Xamarin.Forms.

Nota:

Proporcionar un representador personalizado en cada proyecto de la plataforma es un paso opcional. Si no se registra un representador personalizado, se usará el representador predeterminado de la clase base del control.

El siguiente diagrama muestra las responsabilidades de cada proyecto de la aplicación de ejemplo, junto con las relaciones entre ellos:

Responsabilidades del proyecto de representador personalizado MyEntry

Las clases MyEntryRenderer del representador específico de la plataforma, que se derivan de la clase EntryRenderer para cada plataforma, representan el control MyEntry. Esto da como resultado que cada control MyEntry se represente con un color de fondo específico de la plataforma, como se muestra en las siguientes capturas de pantalla:

Control MyEntry en cada plataforma

La clase EntryRenderer expone el método OnElementChanged, al que se llama cuando se crea el control de Xamarin.Forms para representar el control nativo correspondiente. Este método toma un parámetro ElementChangedEventArgs que contiene propiedades OldElement y NewElement. Estas propiedades representan al elemento de Xamarin.Forms al que estaba asociado el representador y al elemento de Xamarin.Forms al que está asociado el representador, respectivamente. En la aplicación de ejemplo, la propiedad OldElement es null y la propiedad NewElement contiene una referencia al control de MyEntry.

El lugar para realizar la personalización del control nativo es una versión reemplazada del método OnElementChanged en la clase MyEntryRenderer. Una referencia con tipo para el control nativo que se usa en la plataforma puede obtenerse a través de la propiedad Control. Además, se puede obtener una referencia al control de Xamarin.Forms que se representa mediante la propiedad Element, aunque no se usa en la aplicación de ejemplo.

Cada clase de representador personalizado se decora con un atributo ExportRenderer que registra el representador con Xamarin.Forms. El atributo toma dos parámetros: el nombre de tipo del control de Xamarin.Forms que se representa y el nombre de tipo del representador personalizado. El prefijo assembly del atributo especifica que el atributo se aplica a todo el ensamblado.

En las secciones siguientes se describe la implementación de cada clase de representador personalizado MyEntryRenderer específico de plataforma.

Crear un representador personalizado en iOS

El ejemplo de código siguiente muestra el representador personalizado para la plataforma iOS:

using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer (typeof(MyEntry), typeof(MyEntryRenderer))]
namespace CustomRenderer.iOS
{
    public class MyEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged (ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged (e);

            if (Control != null) {
                // do whatever you want to the UITextField here!
                Control.BackgroundColor = UIColor.FromRGB (204, 153, 255);
                Control.BorderStyle = UITextBorderStyle.Line;
            }
        }
    }
}

La llamada al método OnElementChanged de la clase base crea una instancia de un control UITextField de iOS, con una referencia al control que se asigna en la propiedad Control del representador. Después se establece el color de fondo en púrpura claro con el método UIColor.FromRGB.

Crear un representador personalizado en Android

El siguiente ejemplo de código muestra el representador personalizado para la plataforma de Android:

using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace CustomRenderer.Android
{
    class MyEntryRenderer : EntryRenderer
    {
        public MyEntryRenderer(Context context) : base(context)
        {
        }

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

            if (Control != null)
            {
                Control.SetBackgroundColor(global::Android.Graphics.Color.LightGreen);
            }
        }
    }
}

La llamada al método OnElementChanged de la clase base crea una instancia de un control EditText de Android, con una referencia al control que se asigna en la propiedad Control del representador. Después se establece el color de fondo en verde claro con el método Control.SetBackgroundColor.

Creación del representador personalizado en UWP

En el siguiente ejemplo de código se muestra el representador personalizado para UWP:

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace CustomRenderer.UWP
{
    public class MyEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control.Background = new SolidColorBrush(Colors.Cyan);
            }
        }
    }
}

La llamada al método OnElementChanged de la clase base crea una instancia de un control TextBox, con una referencia al control que se asigna en la propiedad Control del representador. Después se establece el color de fondo en cian mediante la creación de una instancia de SolidColorBrush.

Resumen

En este artículo, se ha mostrado cómo crear un representador de control personalizado para el control Entry de Xamarin.Forms, lo que permite que los desarrolladores reemplacen la representación nativa predeterminada por su propia representación específica de la plataforma. Los representadores personalizados proporcionan un método eficaz para personalizar la apariencia de los controles de Xamarin.Forms. Se pueden usar para pequeños cambios de estilo o para una personalización sofisticada del diseño y el comportamiento específicos de una plataforma.