Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Xamarin

Introducción a Xamarin.Forms: Personalización de la Interfaz de Usuario

Spanish (Español) translation by D***C (you can also view the original English article)

1. Preparando el Escenario

Al crear aplicaciones con Xamarin.Forms, sin duda te gustará la simplicidad de crear interfaces de usuario. Con Xamarin.Forms, puedes usar la misma terminología para los controles en varias plataformas.

Si bien este concepto puede ser muy poderoso, como diseñador o desarrollador, puede ser algo limitante. Puede parecer que nos vemos obligados a usar los controles de interfaz de usuario nativos que vienen con cada una de las plataformas sin la capacidad de agregar personalización. Este no es el caso.

Para entrar en el proceso de personalización de la interfaz de usuario para plataformas específicas, primero debes comprender el proceso de representación de Xamarin.Forms.

2. Renderizado de control

Cuando se trata de usar Xamarin.Forms para crear una interfaz de usuario para tu aplicación móvil multiplataforma, hay dos piezas importantes en el rompecabezas que debes entender.

Elemento

La primera pieza del rompecabezas es el elemento. Puedes pensar en un elemento como la definición agnóstica de plataforma de un control dentro de Xamarin.Forms. Si has leído la documentación, sabrás que estos controles también se denominan objetos View. Para ser aún más específicos, cada elemento de Xamarin.Forms deriva de la clase View.

Estos elementos se utilizan para describir un elemento visual. Los elementos proporcionan una definición agnóstica de la plataforma de las características de cómo debe verse y comportarse el control. Un elemento por sí solo no puede crear un control que se muestre al usuario. Necesita ayuda. Aquí es donde entra en juego la segunda parte del proceso de renderizado, un renderizador.

Renderizador

Un renderizador entra en juego cuando se ejecuta la aplicación. El trabajo del renderizador es tomar el elemento agnóstico de la plataforma y transformarlo en algo visual para presentar al usuario.

Por ejemplo, si estuvieras usando un control Label en el proyecto compartido, durante la ejecución de la aplicación, el marco Xamarin.Forms usaría una instancia de la clase LabelRenderer para dibujar el control nativo. Si estás empezando a preguntarte cómo sucede esto desde un proyecto de código compartido, esa es una muy buena pregunta. La respuesta es que no.

Vamos a ilustrar esto con un ejemplo. Comienza abriendo Xamarin Studio o Visual Studio. El proceso y los conceptos son los mismos para ambos. Si usas Xamarin Studio, no hay compatibilidad con proyectos de Windows Phone, por lo que solo crearás tres proyectos en la solución. Si usas Visual Studio, crearás cuatro proyectos.

En Visual Studio, crea un nuevo proyecto y selecciona la familia de proyectos Aplicaciones Móviles a la izquierda y elije la plantilla de proyecto Aplicación en Blanco (Xamarin.Forms Portable) a la derecha. Puedes nombrar tu proyecto como desees, pero si deseas seguirme, usa el nombre Personalización y haz clic en Aceptar.

Ahora, dependiendo de tu IDE, deberías ver tres o cuatro proyectos en tu solución. Si expandes la carpeta Referencias en el proyecto de Personalización (Portátil), verás una referencia de ensamblado a Xamarin.Forms.Core. Aquí es donde se definen todos los diferentes elementos para que los uses en tu proyecto de interfaz de usuario compartida. Nada fuera de lo común allí.

Si abres cada uno de los proyectos específicos de la plataforma y expandes tus carpetas Referencias, verás que cada uno contiene una implementación específica de la plataforma de esa biblioteca Xamarin.Forms, denominada Xamarin.Forms.Platform.Android, Xamarin.Forms.Platform.iOS y Xamarin.Forms.Platform.WP8 respectivamente.

Es en estos ensamblados donde encontrarás los representadores para cada uno de los elementos Xamarin.Forms. Ahora estás comenzando a ver el diseño del proceso. Los elementos independientes de la plataforma, u objetos View, están en el proyecto de código compartido, pero todos los representadores específicos para los elementos están en los proyectos específicos de la plataforma.

Esto significa que para cada uno de los elementos que utilices, habrá dos renderizadores creados en Xamarin Studio y tres en Visual Studio. Ahora que ves cómo se estructura esto en Xamarin.Forms, la siguiente pregunta lógica suele ser: "¿Cuándo debo usar personalizaciones?".

3. Cuándo personalizar

Definitivamente hay un buen número de propiedades y características que se definen dentro de los elementos Xamarin.Forms que se pueden usar para personalizar el control final en cada una de las plataformas. Dicho esto, sin embargo, no todas las personalizaciones disponibles en cada una de las plataformas existen en Xamarin.Forms. Siendo ese el caso, hay dos escenarios principales en los que querrás crear personalizaciones.

El primer escenario en el que se necesitarán personalizaciones es cuando deseas crear un control completamente personalizado. Digamos que deseas crear un control de calendario o tal vez algún tipo de control de gráficos. Desafortunadamente nada de eso existe hoy en día en Xamarin.Forms, lo que no quiere decir que nunca lo hará.

Esta es definitivamente una situación en la que tendrás que comenzar desde el principio y crear todo desde cero. Deberás definir el elemento que vas a utilizar para describir las características del control de una manera independiente de la plataforma. Luego, también deberás crear un renderizador personalizado para cada una de las plataformas que deseas admitir.

Dependiendo de lo que estés construyendo, este puede ser un proyecto bastante extenso. Siendo ese el caso, lo guardaré para otro tutorial en sí mismo. En cambio, en este tutorial, nos centraremos en el segundo escenario en el que necesitarás cierta personalización.

La segunda situación en la que necesitarás cierta personalización es cuando un elemento incorporado no admite una característica específica de una plataforma que deseas admitir. Un ejemplo de esto estaría en el control Label. En Xamarin.Forms, no hay ningún mecanismo, o propiedad, que te permita crear el equivalente en cada una de las plataformas para que el texto esté en negrita o cursiva. Esto puede parecer un escenario muy simple, pero encontrarás que el proceso básico de hacer que este cambio esté disponible en el elemento y hacer que el renderizador lo entienda será el mismo aquí que en algunos de los escenarios más complejos.

Con el segundo escenario en mente, tienes dos opciones. Puedes reemplazar el renderizador existente para una plataforma específica (o para todas las plataformas) y crear su propia funcionalidad y lógica de dibujo para todas las capacidades del elemento. Como alternativa, puedes crear tu propio elemento que se derive del elemento existente y asociar ese nuevo elemento con un representador personalizado. De esta manera, conservarás toda la lógica predeterminada y las capacidades de representación del elemento base y lo personalizas como desees. Esta será la ruta que tomemos para este ejemplo. Ahora, veamos cómo agregar esta funcionalidad a nuestro propio proyecto.

4. Agregar personalización

Comencemos este proceso configurando la estructura básica de nuestra aplicación para que podamos ver nuestra línea de base y luego hacer cambios. Comienza abriendo el archivo App.cs en el proyecto Personalización (Portátil) en el Explorador de Soluciones. Modifica el método GetMainPage para que tenga el siguiente aspecto:

Como puedes ver aquí, hemos creado tres controles de Label simples. Uno quiere estar en cursiva, uno quiere ser audaz, y el tercero es codicioso y quiere ser ambos. Si tuvieras que ejecutar esta aplicación en iOS, Android y Windows Phone, se verían algo como esto:

iOS

Android

Windows Phone

Como puedes ver, no quieren ser tan aburridos. Bueno, no te quedes sentado allí, ayúdalos.

Paso 1: Crear un Nuevo Elemento

Lo primero que debemos hacer es crear un nuevo elemento que podamos usar para proporcionar personalizaciones adicionales al control Label existente. Comienza agregando una nueva clase a tu proyecto de Personalización (Portátil) y nombralo StyledLabel. Reemplaza su contenido por el siguiente:

Definimos una enumeración y una clase muy simples. Hemos definido la enumeración para permitir valores en cursiva, negrita y negrita más cursiva. A continuación, creamos una clase StyledLabel que deriva de la clase base Label y agregamos una nueva propiedad, Style, para mantener el estilo apropiado que queremos aplicar al control.

Para asegurarnos de que todo sigue funcionando, y debería, modifiquemos el archivo App.cs una vez más y reemplacemos los elementos Label en nuestro primer ejemplo con nuestros nuevos elementos StyledLabel. Dado que la clase StyleLabel hereda de la clase Label, todo debería seguir funcionando.

Una vez más, aquí están los resultados de este cambio.

iOS

Android

Windows Phone

Como puedes ver, nada ha cambiado. Ahora que tenemos un nuevo elemento personalizado, es el momento de crear los renderizadores personalizados para encargarse de los controles nativos.

Paso 2: Renderizador de Android

El primer paso para crear un renderizador es agregar una nueva clase a la plataforma a la que se dirige. Comenzaremos con el proyecto Xamarin.Android. Dentro de este proyecto, crea un nuevo archivo de clase y  lo nombras StyledLabelRenderer y reemplaza su contenido por el siguiente:

Echemos un vistazo más de cerca a este bloque de código.

Comenzamos con un atributo de assembly especial que indica a Xamarin.Forms que use esta clase StyledLabelRenderer como representador cada vez que intenta representar objetos StyledLabel. Esto es necesario para que las personalizaciones funcionen correctamente.

Al igual que cuando creamos un nuevo elemento StyledLabel, heredado de la clase Label, haremos que nuestra nueva clase StyledLabelRenderer herede de la clase LabelRenderer. Esto nos permitirá mantener la funcionalidad existente por lo que solo tendremos que anular lo que queremos cambiar o personalizar.

Para aplicar nuestro nuevo formato, vamos a tener que saltar al proceso de renderizado y lo hacemos a través del método OnElementChanged. En este método, podemos hacer todas nuestras personalizaciones.

Al hacer tus personalizaciones, hay dos propiedades muy importantes que utilizarás. Primero, deberás obtener una referencia al elemento original que creaste y que se está representando en nuestro método de renderizado personalizado. Para ello, utiliza la propiedad Element. Este es un objeto genérico, por lo que tendrás que convertirlo en cualquier tipo que estés representando. En este caso, se trata de un StyledLabel.

La segunda propiedad importante que necesitas es la propiedad Control. Esta propiedad contiene una referencia con tipo al control nativo de la plataforma. En este caso, dado que has heredado de la clase LabelRenderer, el código ya sabe que el Control en este caso es un TextView.

A partir de este punto, utilizarás una lógica simple para determinar qué personalización realizar y aplicar las personalizaciones nativas adecuadas. En este caso, utilizarás el mecanismo de Android para modificar el tipo de letra de un TextView mediante el método SetTypeface.

Si tuvieras que ejecutar esta aplicación ahora, deberías ver algo como lo siguiente en el emulador de Android, que es exactamente lo que buscamos.

Paso 3: Renderizador de iOS

El proceso de creación del renderizador de iOS es exactamente el mismo hasta el punto de anular el método OnElementChanged. Comienza creando una nueva clase en su proyecto Customization.iOS. Dale el nombre de StyledLabelRenderer y reemplaza el contenido por el siguiente:

Como ves, todo es exactamente igual. Tiene el mismo atributo de assembly, estás anulando el mismo método OnElementChanged, estás concediendo la propiedad Element a un StyledLabel y tienes el mismo shell de una instrucción switch para trabajar a través de la propiedad Style.

La única diferencia se produce en el lugar donde se aplica el estilo al control UILabel nativo.

La forma de hacer que la propiedad Font de UILabel esté en negrita o cursiva en iOS es a través de un método auxiliar estático en la clase UIFont denominada BoldSystemFontOfSize o ItalicSystemFontOfSize. Eso funcionará en el caso de una fuente en negrita o una fuente en cursiva, pero no en ambas. Si intentas aplicar ambos a un UILabel, solo se renderizará el último.

Para conseguir ambos estilos, haremos un poco de trampa y utilizaremos una fuente incorporada en iOS llamada Helvetica-BoldOblique. Esta fuente tiene negrita y cursiva incorporadas, por lo que no tenemos que hacerlas individualmente.

Ejecutar esto en el simulador de iOS te dará el siguiente resultado:

Paso 4: Renderizador de Windows Phone

Por último, llegamos a Windows Phone. Como ya habrás adivinado, el proceso es exactamente el mismo. Crea una nueva clase en el proyecto Customization.WinPhone, dale el nombre de StyledLabelRenderer y reemplaza el contenido por el siguiente:

Una vez más, todo es igual excepto por la lógica. En este caso, para que el texto quede en cursiva, establece la propiedad FontStyle de TextBlock en Italic. A continuación, para que el texto esté en negrita, establece la propiedad FontWeight en Bold. Si deseas aplicar ambos, simplemente configura ambos.

La ejecución de esta aplicación en el emulador de Windows Phone te dará el siguiente resultado:

Ahora has creado con éxito un elemento multiplataforma totalmente funcional, personalizado y que se representa perfectamente en las tres plataformas. Ahora deberías sentirte listo para enfrentarte al mundo. Bueno, casi.

El proceso que hemos seguido a lo largo de este tutorial es completamente válido y en la mayoría de los casos va a funcionar a la perfección. Sin embargo, hay un caso muy específico en el que nos perderemos alguna funcionalidad si usamos ese enfoque. Ese caso es vinculante de datos en XAML.

5. XAML y Enlace de Datos

Una de las características interesantes de Xamarin.Forms es el hecho de que puedes usar XAML y el enlace de datos tal como lo harías si estuvieras creando una aplicación de Windows Phone, WPF o Silverlight. Desafortunadamente, el enlace de datos y XAML están más allá del alcance de este tutorial, pero te recomiendo que leas más sobre este tema en la página XAML para Xamarin.Forms.

Paso 1: Crear la página XAML

Comencemos por crear una página XAML simple que duplique la interfaz de usuario que hemos creado previamente en el código. Comienza agregando un nuevo archivo al proyecto Customizations (Portable), seleccionando el tipo de archivo Página XAML Forms y asignándole un nombre de StyledLabelPage.

Una vez creado el archivo, reemplaza el contenido por el siguiente:

Este XAML creará exactamente la misma página con la que hemos estado trabajando antes. Ten en cuenta la adición de la declaración de espacio de nombres xmlns:local en la parte superior del archivo, así como el prefijo local: antes de cada referencia a los objetos StyledLabel. Sin estos, el analizador XAML no sabrá qué es un StyledLabel y, en última instancia, no podrá ejecutarse.

Para ejecutar esto, deberás realizar dos pequeñas modificaciones. Primero, abre el archivo App.cs y modifica el método GetMainPage para que tenga este aspecto:

En segundo lugar, abre el archivo StyledLabelPage.xaml.cs y cámbialo para que se vea así:

Ahora, cuando ejecutes tus aplicaciones, deberías obtener los mismos resultados en las tres plataformas. Bastante limpio, ¿eh?

iOS

Android

Windows Phone

Paso 2: Agregar enlace de datos

Si estás familiarizado con el concepto del patrón View View-Model pattern (MVVM), sabrás que una de sus características principales es el enlace de datos. De hecho, este patrón fue diseñado en torno al uso de XAML.

El enlace de datos es el proceso de permitir que las propiedades de dos objetos se vinculan entre sí para que un cambio en uno cree un cambio en el otro. El proceso de enlace de datos dentro de XAML se logra mediante el uso de la Extensión de Marcado de Enlace.

Las extensiones de marcado no son una característica de Xamarin.Forms, ni siquiera de XAML. En realidad, es una característica de XML que permite aplicar funcionalidad adicional al proceso de establecer el valor de un atributo en un elemento.

Por ejemplo, echemos un vistazo más de cerca al primer elemento StyledLabel en el ejemplo anterior.

El problema con este marcado es que todas las propiedades (atributos) se asignan explícitamente. Esto crea un diseño bastante inflexible. Entonces, ¿qué sucede si por alguna razón durante la ejecución de nuestra aplicación, queremos cambiar el atributo Style para que tenga un valor de Bold? Bueno, en nuestro archivo de código subyacente, tendríamos que observar un evento, capturar ese evento, obtener esta instancia del elemento StyledLabel y modificar este valor de atributo. Eso suena como mucho trabajo. ¿No sería bueno si pudiéramos facilitar ese proceso? Bueno, podemos.

Extensión de Marcado de Enlace

La forma en que puedes hacer que este diseño sea más flexible para la modificación es mediante el uso de la extensión de marcado Binding. La forma de usar esta extensión es modificando el marcado para que tenga el siguiente aspecto:

Como puedes ver, hemos cambiado el valor de la propiedad Style a {Binding FirstStyle}. El uso de una extensión de marcado se suele decir mediante el uso de llaves rizadas {}. Esto significa que lo que esté contenido dentro de los brackets rizados va a ser una extensión de marcado.

En este caso, estamos utilizando la extensión Binding. La segunda parte de esta extensión es el nombre de una propiedad que queremos enlazar a esta propiedad (atributo). En este caso, lo llamaremos FirstStyle. Eso aún no existe, pero nos encargaremos de eso en un momento. Primero, actualicemos completamente este archivo para aprovechar el enlace de datos.

BindingContext

Dado que estamos creando un enlace, por definición estamos tratando de vincular este atributo XAML a otra cosa que permita que estas dos propiedades compartan sus datos. Para ello, primero deberás crear una clase que contenga propiedades con los mismos nombres que estamos usando en el ejemplo XAML anterior.

Crea una nueva clase dentro del proyecto Customizations (Portable) y asígnale el nombre SampleStyles y reemplaza el contenido por el siguiente:

Esta es una clase muy simple que contiene tres propiedades de tipo StyleType con los mismos nombres que usamos en nuestro Binding de los atributos. Ahora tenemos el XAML usando la extensión de marcado Binding y una clase que contiene propiedades con el mismo nombre que vemos en los enlaces en el XAML. Solo necesitamos pegamento para juntarlos. Ese pegamento es el BindingContext.

Para vincular las propiedades de estos objetos, necesitamos asignar una instancia de la clase SampleStyles a la propiedad BindingContext de StyledLabelPage. Abre el archivo StyledLabelPage.xaml.cs y modifica el constructor para que sea similar al siguiente:

En teoría, si ejecutaras tu aplicación, el archivo XAML se rellenará con los valores de nuestras propiedades SampleStyles y todo se representaría en la pantalla como vimos antes. Lamentablemente no es así. Terminas obteniendo una excepción en tiempo de ejecución que se ve así:

Si miras Información adicional, verás que el problema es que No se encontró ninguna propiedad de estilo de nombre. Esto es el resultado de la forma en que creamos el StyledLabel al principio. Para aprovechar el enlace de datos, las propiedades deben ser del tipo BindableProperty. Para ello, tendremos que hacer una pequeña modificación en nuestra clase StyledLabel.

Como puedes ver, hemos agregado una propiedad estática llamada StyleProperty de tipo BindableProperty. Luego le asignamos el resultado de un CreateMethod que define al dueño de la propiedad con la que estamos trabajando.

La propiedad es Style, pero el propietario es StyledLabel. El segundo parámetro genérico es el tipo devuelto de la propiedad, que es StyleType. Entonces, el único argumento que estamos proporcionando al método es una expresión que define lo que se devuelve y un valor predeterminado. En nuestro caso, estamos devolviendo el valor de la propiedad de instancia Style y el valor predeterminado será None o no styling.

A continuación, debemos modificar la implementación de la propiedad Style para aplazar la funcionalidad de obtención y configuración a la clase base, de modo que BindingProperty se actualice correctamente si cambia el valor de la propiedad Style.

Ahora, si volvieras a ejecutar tu aplicación, deberías ver que todo funciona como se esperaba.

iOS

Android

Windows Phone

Conclusión

En este tutorial, aprendiste sobre un concepto muy importante en el mundo de Xamarin.Forms, la personalización. La personalización es una de las características clave que les permite destacarse de la competencia.

Saber cómo, cuándo y dónde personalizar es una habilidad muy importante para tener como desarrollador móvil. Espero que encuentres estas habilidades útiles y seas capaz de darles un buen uso en tu próximo proyecto.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.