Personalización de controles Xamarin.Forms

*Introducción

En Xamarin.Form es que es posible personalizar los controles UI específicos para cada plataforma utilizando Custom Renderers. Esto se realiza mediante la directriz ExportRenderer. Las interfaces de usuario Xamarin.Forms se representan mediante los controles nativos de la plataforma de destino, permitiendo que las aplicaciones Xamarin.Forms para conservar el aspecto adecuado y se sensación para cada plataforma. Los Renderizadores personalizados permiten anular este procedimiento para personalizar la apariencia y el comportamiento de los controles Xamarin.Forms en cada plataforma.

Cada control de Xamarin.forms tiene un renderizador para cada plataforma que crea una instancia de de control nativo. Cuando un control "Entry" es renderizado por una aplicacion de Xamarin.forms, en iOS la clase "EntryRender" es instanciada que a su vez crea una instancia de control "UITextField" nativa. en la plataforma Android , la clase "EntryRender" instancia un control "EditText". En la plataforma WindowsPhone, la clase "EntryRender" instancia un control "UserControl"

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

A continuación veremos un ejemplo sencillo donde personalizamos un control para cada plataforma.

[assembly: ExportRenderer(typeof(Clase en el proyecto Portable), typeof(Clase del proyecto de plataforma))]

*Creando el proyecto

image

1.Seleccionar "Cross-Platform"
2.Selección de una plantilla a utilizar "Blank App (Xamarin.Forms.Portable"
3.Nombre de la aplicación en este caso se llamara "AppExportRenderXF"
4.Presionar el botón de "Aceptar" para crear el proyecto

*Creando el control Custom Entry

En nuestro proyecto portable creamos una clase llamada "CustomEntry" que hereda de Entry:

using Xamarin.Forms;

namespace AppExportRenderXF
{
    public class CustomEntry : Entry
    {
    }
}

 

*Creando el Custom Render en cada plataforma

1.Crear una subclase de la clase "EntryRender" que representa al control nativo.

2.Sobrescribir el método "OnElementChanged" que renderiza el control nativo y escribir la lógica para el control personalizado. Este método es llamado cuando el correspondiente control Xamarin.forms es creado.

3.Agregar un atributo "ExportRender" a la clase "CutomEntryRender" para especificar que será usado para renderizar el control Xamarin.Forms. Este atributo es usado para registrar el control personalizado con Xamarin.Forms.

A continuación , implementamos la personalización de dicho control en Android "AppExportRenderXF.Droid" creamos una clase llamada "CustomEntryRender" y codificamos lo siguiente:

using AppExportRenderXF;
using AppExportRenderXF.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRender))]
namespace AppExportRenderXF.Droid
{
    public class CustomEntryRender : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
                Control.SetBackgroundColor(global::Android.Graphics.Color.DarkGray);
        }
    }
}

Ahora en en el proyecto de iOS "AppExportRenderXF.iOS" creamos una clase llamada "CustomEntryRender"  y se codifica lo siguiente:

using AppExportRenderXF;
using AppExportRenderXF.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRender))]
namespace AppExportRenderXF.iOS
{
    public class CustomEntryRender : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                Control.BackgroundColor = UIColor.LightGray;
                Control.BorderStyle = UITextBorderStyle.Line;
            }
        }
    }
}

Y por ultimo en el Proyecto de Windows Phone "AppExportRenderXF.WinPhone" cremos la clase llamada "CustomEntryRender"  y se codifica lo siguiente:

using Windows.UI;
using Windows.UI.Xaml.Media;
using AppExportRenderXF;
using AppExportRenderXF.WinPhone;
using Xamarin.Forms;
using Xamarin.Forms.Platform.WinRT;

[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRender))]
namespace AppExportRenderXF.WinPhone
{
    public class CustomEntryRender : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

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

Se puede ver que en la inyección de dependencia [assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRender))] en "CustomEntry" es la clase en el proyecto Portable  y "CustomEntryRender " el nombre de la clase en el proyecto de plataforma especifica.

*Consumiendo el Custom Entry

Después de haber creado lo anterior, en el proyecto Portable vamos a probar, para eso vamos a crear lo siguiente:

image1. Clic derecho sobre el proyecto portable y en el menú de opciones seleccionar "Agregar"

2. Elegir la opción de nuevo elemento, para que se muestre el siguiente cuadro de dialogo.

image

1.Seleccionar "Cross-Platform"

2.Selección de una plantilla a utilizar "Forms Xaml Page"

3.Nombre de la plantilla en este caso se llamara "HomePage"

4.Presionar el botón de "Aceptar" para crear la pagina que contendrá Xaml

A la pagina creada agregar el siguiente Código Xaml

<?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:local="clr-namespace:AppExportRenderXF;assembly=AppExportRenderXF"
             x:Class="AppExportRenderXF.HomePage" >
  <StackLayout>
 <local:CustomEntry Placeholder="Inserte Texto"></local:CustomEntry>
  </StackLayout>
</ContentPage>

Notar que el código xmlns:local="clr-namespace:AppExportRenderXF;assembly=AppExportRenderXF" declaramos un espacio de nombre del ensamblado con el nombre del proyecto para usarla con la palabra "local" y esto es para poder accesar a las clases de código c# que tenemos en en el proyecto.

El código <local:CustomEntry Placeholder="Inserte Texto"></local:CustomEntry> se esta utilizando la clase "CustomEntry" que hereda de "Entry" que se creo al inicio de este post.

*Ejecutando el proyecto en cada plataforma

para ejecutar el proyecto, se tiene que indicar en el punto de entra en la clase "App.cs" que tiene que ejecutar la pagina que se ha creado

using Xamarin.Forms;

namespace AppExportRenderXF
{
    public class App : Application
    {
        public App()
        {
            MainPage = new NavigationPage(new HomePage());
        }
	}
 }

Ahora ejecutamos en Android y en iOS se obtendrá el siguiente resultado:

image image

Analizando el código, podemos darnos cuenta que existen diferencias incompatibles entre plataformas por la forma en que se procesan sus datos y la arquitectura, por lo que es necesario que en funcionalidades como estas desarrollemos el código especifico para la plataforma.

One thought on “Personalización de controles Xamarin.Forms

Deja un comentario