[Xamarin.Forms] Backgrounding y persistencia de datos

Save-01-WFIntroducción

En dispositivos móviles contamos con una aplicación en primer plano. Cuando cambiamos de aplicación, si el usuario vuelve a la anterior, normalmente las aplicaciones vuelven a la última pantalla en la que se encontraba el usuario, con los datos e información que el usuario dejo. Todo listo y preparado para continuar. Un detalle que parece trivial pero que hoy día es necesario y esperado en cualquier aplicación.

Como desarrolladores debemos conocer el ciclo de vida de las aplicaciones móviles, la gestión y persistencia de información y como aplicar todo ese conocimiento para otorgar la mejor experiencia posible al usuario en cada plataforma.

En este artículo, vamos a aprender como realizar la persistencia de información de la aplicación en el ciclo de vida de la misma en Xamarin.Forms.

Eventos ciclo de vida

En Xamarin.Forms contamos con la clase Application donde establecemos el punto de entrada de la aplicación además de contar con métodos virtuales que podemos sobreescribir para gestionar el ciclo de vida de la aplicación:

  • OnSleep: Este evento se lanza cuando la aplicación pasa a background.
  • OnResume: Lanzado cuando la aplicación se resume después de estar en background.
protected override void OnStart()
{
    Debug.WriteLine ("OnStart");
}
protected override void OnSleep()
{
    Debug.WriteLine ("OnSleep");
}
protected override void OnResume()
{
    Debug.WriteLine ("OnResume");
}

Properties Dictionary

Desde la llegada de Xamarin.Forms 1.3 tenemos a nuestra disposición Application.Current.Properties. Ideal para utilizar en la suspensión y reanudación de la aplicación. Estamos ante un Dictionary con un uso muy sencillo que se encarga automáticamente del almacenamiento de datos en local.

Guardar

Utilizando Application.Current.Properties bastará con crear una nueva clave y asignar el valor:

Application.Current.Properties ["value"] = 1;

Leer

Recuperamos el valor utilizando la clave:

if (Application.Current.Properties.ContainsKey("value"))
{
     var val = Convert.ToInt32(Application.Current.Properties["value"]);
}

NOTA: Importante resaltar que como con el trabajo de cualquier diccionario, debemos verificar previamente la existencia del valor dado la clave otorgada.

Eliminar

En caso de desear eliminar el valor, de nuevo utilizamos la clave:

if (Application.Current.Properties.ContainsKey("value"))
{
     Application.Current.Properties.Remove("value");
}

Detalles a tener en cuenta

Debemos tener en cuenta que:

  • El valor asignado a una clave solo se guardará cuando se realice la suspensión de la aplicación (método OnSleep()). Es importante tener este detalle en cuenta ya que ante un cierre inesperado o bien en depuración al parar la misma, no guardaremos el valor al no realizarse la suspensión.
  • Al trabajar con un diccionario podemos guardar practicamente cualquier cosa, incluso entidades de clases propias que se serializarán.
  • Con Xamarin.Forms 1.4 se añadió un método adicional llamado SavePropertiesAsync() que podemos utilizar para guardar programáticamente cualquier cambio.

Persistencia de datos en Apps Xamarin.Forms

Para probar la persistencia de información junto al ciclo de vida de la aplicación vamos a crear un ejemplo Xamarin.Forms sencillo donde tendremos un formulario básico y guardaremos y recuperaremos la información al suspender y reanudar la aplicación.

Creamos la interfaz básica a utilizar:

<Grid
    VerticalOptions="Start">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="100" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Label Grid.Column="0" Grid.Row="0" Text="First Name" VerticalOptions="End" />
    <Entry Grid.Column="1" Grid.Row="0" Text="{Binding FirstName, Mode=TwoWay}" />
</Grid>

El resultado:

Nuestra UI
Nuestra UI

En la viewmodel la propiedad bindeada:

private string _firstName;

public string FirstName
{
     get { return _firstName; }
     set
     {
          _firstName = value;
          RaisePropertyChanged();
     }
}

En la clase Application contamos con los métodos para gestionar el ciclo de vida de la aplicación. Como hemos visto, contamos con el método OnSleep() lanzado cuando la aplicación pasa a segundo plano. En este punto accederemos a la propiedad FirstName bindeada a la UI de la viewmodel y la guardaremos utilizando Properties Dictionary:

Application.Current.Properties["FirstName"] = viewModel.FirstName;   

Cuando la aplicación se resume, se lanza el evento OnResume(). En este punto verificamos la existencia de la propiedad FirstName y en caso de existir, la asignamos en nuestra viewmodel:

if (Application.Current.Properties.ContainsKey("FirstName"))
{
     var firstName = (string)Application.Current.Properties["FirstName"];
  
     viewModel.FirstName = firstName;
}

Podéis acceder al código fuente directamente en GitHub:

Ver GitHub

Más información

[Material SVQXDG] Sevilla Xamarin Dev Day

RDXWoY7W_400x400El evento

El pasado 06 de Abril, desde el grupo SVQXDG, desarrolladores Xamarin de Sevilla, organizábamos el Sevilla Xamarin Dev Day. Un evento donde tener hueco a sesiones técnicas, analizar y aclarar cualquier duda relacionada con los últimos anuncios del //BUILD 2016 además de tener momento para el networking y algun que otro detalle con los asistentes.

El material

En mi caso, pude participar con una sesión casi obligatoria donde repasábamos los cambios fundamentales anunciados en el pasado //BUILD como:

  • Xamarin incluido sin coste adicional en todas las versiones de Visual Studio.
  • Xamarin Core o Xamarin.Forms Open Source.
  • La integración de Xamarin Insights a HockeyApp.
  • Otros aspectos como el progreso de Xamarin Test Cloud, Xamarin University, etc.

La presentación utilizada la tenéis disponible a continuación:

Posteriormente, continuamos con una sobre de desarrollo con Xamarin.Forms, donde vimos todas las claves para adaptar las aplicaciones a tabletas.

En cuanto a las demos técnicas realizadas, las tenéis disponible en GitHub:

Ver GitHub

Quisiera terminar añadiendo algunos agradecimientos a Josué Yeray y Marcos Cobeña por participar junto a un servidor en las sesiones y por supuesto, muchas gracias a todos los asistentes.

Más información

[Xamarin.Forms] Utilizando Messaging Center

Mail Next-WFIntroducción

En el desarrollo de aplicaciones móviles multiplataforma con Xamarin es habitual utilizar el patrón MVVM para separar la vista de la lógica de negocio de la aplicación. De esta forma, podemos conseguir objetivos claves fundamentales como:

  • Nos permite dividir el trabajo de manera muy sencilla (diseñadores – desarrolladores)
  • El mantenimiento es más sencillo.
  • Permite realizar Test a nuestro código.
  • Permite una más fácil reutilización de código.
  • Compartir más código.

Xamarin.Forms incluye un completo sistema de enlace a datos y servicio de dependencias que nos permite realizar una completa implementación del patrón con facilidad. Sin embargo, en ocasiones, necesitamos ciertas «piezas» que nos permitan solucionar problemas existentes manteniendo la arquitectura intacta. En ocasiones realizamos cambios en un elemento de una vista que afecta a otro elemento correspondiente de otra. En este caso, debemos notificar de una viewmodel a otra del cambio.

¿Cómo lo hacemos?

Mensajes

Si has desarrollado previamente utilizando el patrón MVVM utilizando (o no) un framework posiblemente hayas utilizado lo que se conoce como sistema de mensajes. Basicamente la mensajería de basa en el patrón de diseño publish/subscribe. Contamos con tres grandes protagonistas:

  • Mensajes: Información a enviar normalmente relacionada con la lógica de negocio.
  • Publicadores: Cuando un evento ocurre, ya sea un simple click de un botón o una lógica compleja, los publicadores toman la información a enviar y publican el mensaje.
  • Subscriptores: En el lado opuesto, tenemos a los subscriptores que esperan la publicación de un mensaje de un tipo específico para captarlo con toda la información enviada y actuar en consecuencia.

Messaging Center

Xamarin.Forms cuenta con MessagingCenter para permitir la comunicación entre viewmodels u otros componentes sin que tengan que tener referencias entre ambos utilizando el patrón publish/subscribe.

Para probar MessagingCenter vamos a crear una aplicación Xamarin.Forms sencilla donde tendremos dos vistas. La primera vista mostrará un mensaje y un botón además de suscribirse a un mensaje de cambio. El mensaje se modificará utilizando MessagingCenter mientras que el botón permitirá navegar a la segunda vista. Al navegar a la segunda vista se publicará el mensaje de modo que, al regresar a la primera vista el mensaje será modificado.

Definimos la interfaz de la primera vista:

<StackLayout Padding="10" Spacing="10">
     <Label Text="{Binding Info}" />
     <Button 
          Text="Navigate to Second View"
          Command="{Binding NavigateCommand}"/>
</StackLayout>

El resultado:

Nuestra interfaz
Nuestra interfaz

En la viewmodel correspondiente a la vista definimos la propiedad que utilizaremos para mostrar el mensaje:

public string Info
{
     get { return _info; }
     set
     {
          _info = value;
          RaisePropertyChanged();
     }
}

Y el comando que permitirá la navegación a la segunda vista:

private ICommand _navigateCommand;

public ICommand NavigateCommand
{
     get { return _navigateCommand = _navigateCommand ?? new DelegateCommand(NavigateCommandExecute); }
}

public void NavigateCommandExecute()
{
     _navigationService.NavigateTo<SecondViewModel>();
}

En la primera vista vamos a suscribirnos a un mensaje. En Xamarin.Forms contamos con MessagingCenter que cuenta con dos partes fundamentales:

  • Suscripción (Subscribe): Se suscribe a un mensaje concreto para lanzar una acción.
  • Envío (Send): Publica un mensaje para ser captado por suscriptores. Si no existiese ningún subscriptor, el mensaje es ignorado.

La clase MessagingCenter es una clase estática que cuenta con varias sobrecargas del los métodos Subscribe y Send.

Podemos subscribirnos a un mensaje simple con una cadena:

Xamarin.Forms.MessagingCenter.Subscribe<FirstViewModel>(this, "Change", (sender) =>
{
     Info = "Changed from Messaging Center";
});

La viewmodel de la primera vista se subscribe a un mensaje de tipo string con el mensaje «Change».

Navegamos a la segunda vista:

Segunda vista
Segunda vista

En la viewmodel de la segunda vista procedemos a enviar un mensaje de tipo cadena con el valor «Change»:

Xamarin.Forms.MessagingCenter.Send(App.Locator.FirstViewModel, "Change");

Al regresar a la vista anterior, el mensaje ha cambiado con la lógica ejecutada en la subscripción del mensaje:

Mensaje recibido
Mensaje recibido

Sencillo, ¿cierto?

Pasar parámetros como argumento

Podemos pasar un argumento como parámetro del método Send:

MessagingCenter.Send(App.Locator.FirstViewModel, "Change", "Argument");

En la subscripción podemos capturar el parámetro de forma sencilla:

MessagingCenter.Subscribe<FirstViewModel>(this, "Change", (sender, arg) => {
    // Acceso a 'arg' para obtener el parametero
});

Podéis encontrar en GitHub el ejemplo de este artículo:

Ver GitHub

Recordad que cualquier duda o sugerencia la podéis dejar en los comentarios del blog.

Más información

[Evento SVQXDG] Sevilla Xamarin Dev Day

Xamarin LogoEl evento

En Sevilla, existen empresas y desarrolladores con un enorme talento utilizando Xamarin para sus desarrollos de Apps móviles. Con este crisol nació SVQXDG, o lo que es lo mismo, grupo de desarrolladores Xamarin de Sevilla. Es un grupo de usuario donde se busca tener un punto habitual de reunión para ayudar, compartir y aprender entre todos.

Continuamos con fuerza en el grupo organizando un nuevo evento completo con múltiples sesiones buscando cubrir múltiples aspectos relacionados con el desarrollo de aplicaciones Xamarin.

Tendremos la siguiente agenda:

  • 18:00h – 18:45h: Adaptar Apps Xamarin.Forms a teléfonos y tabletas. En esta sesión de la mano de Javier Suárez veremos como adaptar nuestras aplicaciones para otorgar la mejor experiencia posible en teléfonos y tabletas. Como adaptar vistas, tener vistas específicas, adaptar navegación o detectar DPIs y tamaño de pantalla serán algunos de los puntos que veremos.
  • 18:50h – 19:35h: Gestión de notificaciones Push en Apps Xamarin con Azure. Josué Yeray nos enseñará en esta sesión como usar notifications hubs de Azure para enviar notificaciones facilmente a cualquier plataforma. Veremos como funcionan las notificaciones push en cada plataforma así como implementarlas de forma sencilla.
  • 18:40h – 20:25h: Trucos y claves de App Xamarin hasta su llegada en la Store. Terminaremos el evento con una completa sesión de Marcos Cobeña en la que nos mostrará los detalles y claves a tener en cuenta en el desarrollo de una App Xamarin real ¡Buenos días! aro, desde su desarrollo hasta tenerla en la Store.

El lugar

El evento se celebrará en la ETS de Ingeniería Informática. Dirección detallada:

E.T.S. Ingeniería Informática – Universidad de Sevilla
Av. Reina Mercedes s/n
Sevilla Se 41012

ETS Ingeniería Informática
ETS Ingeniería Informática

La fecha

El evento tendrá lugar el próximo Miércoles, 06 de Abril de 18:00h a 20:30h. Tendremos tres sesiones de 45 minutos de duración cada una.

¿Te apuntas?

Más información

[Xamarin.Forms] Optimizando listados con estrategias de cacheo

JumpListXamarin.Forms 2.0

Con la llegada de Xamarin 4 han aterrizado una gran cantidad de diversas novedades entre las que destaca la versión 2.0 de Xamarin Forms. Entre las novedades principales contamos con:

  • Soporte a UWP.
  • Compilación de XAML (XAMLC).
  • Optimización en Layouts.
  • Optimización de listados. Incluidas nuevas estrategias de cacheo.
  • Corrección de bugs.

Optimizando listados

Entre el listado de controles fundamentales de cualquier aplicación, junto a textos, cajas de textos y botones, destacaríamos los listados. Es un control muy habitual en la inmensa mayoría de aplicaciones.

Como hemos visto en el listado de novedades de Xamarin.Forms 2.0, se han introducido mejoras en el rendimiento del control listView incluyendo nuevas estrategias de cacheo.

Estrategias de cacheo

A menudo, en listados debemos soportar grandes cantidades de elementos muy superiores a lo que se puede mostrar en pantalla e incluso a lo que se puede alcanzar con un ligero scroll. Esto impacta negativamente en el rendimiento. Tanto en iOS como en Android contamos con mecanismos de reciclado de celdas que permiten solucionar o mitigar este problema. La técnica consiste en contar solo en memoria con una pequeña cantidad de celdas en memoria de modo que se van reciclando y reutilizando elementos según el usuario realiza scroll.

Con la llegada de Xamarin.Forms 2.0 podemos aprovechar estas características nativas desde Forms. El control ListView recibe una nueva propiedad llamada CachingStrategy para esteblecer el tipo de cacheo realizado. Soporta uno de los siguientes valores:

  • RetainElement: Comportamiento por defecto. Genera una celda diferente por cada elemento del listado. Es recomendable su uso en caso de gran cantidad de cambios en el contexto. Sin embargo, hay que tener en cuenta que el código de inicialización de cada celda se ejecutará por cada celda pudiendo afectar al rendimiento.
  • RecycleElement: Esta opción toma ventajas de los mecanismos nativos de iOS y Android para el reciclado de celdas. Recomendable su uso cuando las celdas no tienen grandes cambios de contexto y su layout es similar. Reduce el consumo de memoria y la rapidez de uso.

Para realizar pruebas de rendimiento, crearemos un sencillo ejemplo con un listado con un número elevado de elementos (monos). En nuestra ViewModel creamos un listado:

[sourcecode language="vb"]
public ObservableCollection<Monkey> Monkeys
{
     get { return _monkeys; }
     set
     {
          _monkeys = value;
          RaisePropertyChanged();
     }
}
[/sourcecode]

Creamos un listado aleatorio de 1000 elementos:

[sourcecode language="vb"]
_count = 1;
Random random = new Random();
for (int i = 0; i < 1000; i++)
{
     Monkeys.Insert(0,
          new Monkey
          {
               Name = string.Format("Monkey {0}", _count),
               Location = Countries[random.Next(0, Countries.Count)],
               Photo = Images[random.Next(0, Images.Count)]
          });
     _count++;
}
[/sourcecode]

En la interfaz, utilizamos el control ListView utilizando el reciclado de celdas:

[sourcecode language="vb"]
<ListView
     ItemsSource="{Binding Monkeys}"
     CachingStrategy="RecycleElement">
     <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <StackLayout Orientation="Vertical">
            <StackLayout Orientation="Horizontal">
              <Image Source="{Binding Photo}"
                     Aspect="AspectFill"
                     WidthRequest="100"/>
              <Label Text="{Binding Name}"
                     VerticalOptions="Center"/>
              <Label Text="{Binding Location}"
                     HorizontalOptions="EndAndExpand"
                     VerticalOptions="Center"/>
            </StackLayout>
          </StackLayout>
        </ViewCell>
      </DataTemplate>
     </ListView.ItemTemplate>
</ListView>
[/sourcecode]

El resultado:

Reciclando celdas
Reciclando celdas

Tenéis el código fuente disponible en GitHub:

Ver GitHub

Recordad que podéis dejar cualquier comentario, sugerencia o duda en los comentarios.

Más información

[VideoBlog] Acelerando el desarrollo en Xamarin

Introducción

Cada vez que nos llega a los desarrolladores un nuevo SDK, es un momento especial con una mezcla de altísima curiosidad y ganas de probar novedades. Entre las novedades principales siempre hay nuevas APIs, controles y otros elementos para poder realizar Apps que antes no eran posibles. Sin embargo, entre el conjunto de novedades siempre suelen venir nuevas herramientas que facilitan ciertas tareas: obtener más analíticas, mejores medidores de rendimiento, crear pruebas de UI, etc.

A parte de las herramientas oficiales que nos llegan por otro lado, la incansable comunidad sigue su ritmo lanzando su propias herramientas. En el VideoBlog de hoy nos centramos en las últimas herramientas más destacadas que llegan de la comunidad para facilitarnos la vida y aumentar nuestra productividad.

Continuous Coding, Xamarin.Forms Player y Gorilla Player

Trataremos tres herramientas diferentes:

  • Xamarin.Forms Player: El objetivo principal es permitir ver cualquier cambio visual en layouts, estilos o imágenes de forma inmediata sin necesidad de compilar.
  • Gorilla Player: Ver cambios de UI al vuelo en una App Xamarin.Forms además de poder usar datos de prueba, modificar estilos o detectar errores de marcado XAML.
  • Continuous Coding: La propuesta es reducir al máximo el ciclo de compilar y ejecutar permitiendo en tiempo real evaluar el código tanto de la lógica como por puesto a nivel de UI. Poder contruir la interfaz al vuelo viendo directamente los resultados de cada línea aplicada además de poder enlazar la misma con la lógica y el backend segun vamos escribiendo.

Recordar que cualquier sugerencia o duda la podéis dejar en los comentarios tanto del blog como del video.

Más información

[Xamarin.Forms] Diferentes plantillas en listado, utilizando DataTemplateSelectors

Black List-WFLlega Xamarin.Forms 2.1

Tras el lanzamiento de Xamarin.Forms 2.0 con grandes novedades como el soporte Preview de UWP o las importantes mejoras en rendimiento, todo continua su curso y tenemos ya disponible Xamarin.Forms 2.1. Contamos con las siguientes mejoras:

  • Efectos: Los efectos llegan como una nueva forma de personalizar aspecto y comportamiento de controles sin necesidad de realizar Custom Renders.
  • ControlTemplates: TemplatedPage y TemplatedView sirven ahora como clase base para ContentPage y ContentView. Se pueden usar para definir la apariencia de un control o página manteniendo una clara separación entre la jerarquía visual y el contenido.
  • DataTemplateSelectors: Poder elegir en tiempo de ejecución la plantilla a utilizar en cada elemento un listado.
  • Otros: Añadida virtualización en UWP, corrección de bugs, etc.

En este artículo vamos a centrarnos en el uso de DataTemplateSelectors en Xamarin.Forms.

DataTemplateSelectors

El objetivo de nuestro ejemplo será mostrar diferentes elementos a nivel visual en un listado. Por ejemplo, en un listado mostrando las actividades del día para una agenda, mostrar de forma visual los elementos de forma diferenciada cada tipo de actividad.

Vamos a crear un ejemplo con el ya utilizado previamente listado de monos. Algunos de ellos contarán con foto disponible mientras que otros no. Vamos a utilizar una plantilla diferente en cada caso.

Comenzamos creando en la viewmodel de la vista una colección con nuestros monos:

public ObservableCollection<Monkey> Monkeys { get; set; }

Para centrar la atención absoluta en el uso de diferentes plantillas, la carga de monos la haremos de la forma más simple posible:

private void LoadMonkeys()
{
     Monkeys = new ObservableCollection<Monkey>();

     Monkeys.Add(new Monkey
     {
          Name = "Baboon",
          Description = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae.",
          Image = "http://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
     });

     Monkeys.Add(new Monkey
     {
          Name = "Capuchin Monkey",
          Description = "The capuchin monkeys are New World monkeys of the subfamily Cebinae. Prior to 2011, the subfamily contained only a single genus, Cebus."
     });

     Monkeys.Add(new Monkey
     {
          Name = "Blue Monkey",
          Description = "The blue monkey or diademed monkey is a species of Old World monkey native to Central and East Africa, ranging from the upper Congo River basin east to the East African Rift and south to northern Angola and Zambia"
     });

     ...
}

Creamos directamente una colección local. Como podemos ver, cada mono esta representado por nombre, descripción y foto. Sin embargo, algunos de ellos no cuentan con foto. En nuestra interfaz:

<ListView
     x:Name="list"
     ItemsSource="{Binding Monkeys}"
     CachingStrategy="RecycleElement">
</ListView>

Utilizaremos un ListView bindeado a la colección de monos.

NOTA: Desde Xamarin.Forms 2.0, el control ListView recibe una nueva propiedad llamada CachingStrategy para esteblecer el tipo de cacheo realizado.

Para la representación de elementos podemos utilizar la propiedad ItemTemplate del control junto a una plantilla. En nuestro caso, deseamos que los elementos con foto se muestren de forma diferente a cuando no contamos con foto.

Crearemos dos plantillas. Por un lado la plantilla para elementos con foto:

<DataTemplate x:Key="MonkeyTemplate">
     <ViewCell Height="200">
          <ViewCell.View>
            <Grid BackgroundColor="#d3d3d3">
              <Grid.RowDefinitions>
                <RowDefinition Height="20" />
                <RowDefinition Height="30" />
              </Grid.RowDefinitions>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="40" />
              </Grid.ColumnDefinitions>
              <Label Grid.Row="0" Grid.Column="0"
                     Text="{Binding Name}" LineBreakMode="TailTruncation" />
              <Label Grid.Row="1" Grid.Column="0"
                     Text="{Binding Description}" Font="Small" TextColor="Gray" 
                     LineBreakMode="TailTruncation" />
              <Image Grid.Row="0" Grid.RowSpan="2" Grid.Column="1"
                     Source="{Binding Image}" Aspect="AspectFill" />
            </Grid>
          </ViewCell.View>
     </ViewCell>
</DataTemplate>

Sin foto:

<DataTemplate x:Key="NoPhotoTemplate">
     <ViewCell>
          <ViewCell.View>
            <StackLayout BackgroundColor="#d3d3d3">
              <Label Text="{Binding Name}" HorizontalOptions="End" />
              <Label Text="{Binding Description}" HorizontalOptions="Start"
                     Font="Small" TextColor="Gray" />
            </StackLayout>
          </ViewCell.View>
     </ViewCell>
</DataTemplate>

Llega el momento de añadir la lógica específica para asociar la plantilla adecuada a cada elemento en tiempo de ejecución. Crearemos una clase derivada de DataTemplateSelector:

public class MonkeyDataTemplateSelector : DataTemplateSelector

La clave la clase será el método OnSelectTemplate. Este método se lanzará por cada elemento del listado y es donde añadiremos la lógica específica para seleccionar la plantilla correspondiente. En nuestro ejemplo, crearemos dos variables de tipo DataTemplate donde tendremos cada una de las plantillas previas creadas en los recursos de la aplicación.

public class MonkeyDataTemplateSelector : DataTemplateSelector
{
     private readonly DataTemplate _monkey;
     private readonly DataTemplate _noPhoto;

     public MonkeyDataTemplateSelector()
     {
         _monkey = (DataTemplate)App.Current.Resources["MonkeyTemplate"];
         _noPhoto = (DataTemplate)App.Current.Resources["NoPhotoTemplate"];
     }

     protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
     {
         if (item is Monkey)
         {
             if(!string.IsNullOrEmpty(((Monkey)item).Image))
                 return _monkey;
         }

         return _noPhoto;
     }
}

Verificamos que el tipo de objeto bindeado en cada elemento es de tipo Monkey y verificamos si cuenta con foto o no. Dependiendo de ello, devolveremos una plantilla u otra.

En nuestra interfaz, utilizaremos el selector de plantilla en la propiedad ItemTemplate:

<ListView
     x:Name="list"
     ItemsSource="{Binding Monkeys}"
     CachingStrategy="RecycleElement">
     <ListView.ItemTemplate>
       <template:MonkeyDataTemplateSelector/>
     </ListView.ItemTemplate>
</ListView>

Todo listo!. Sencillo, ¿cierto?. Si ejecutamos la aplicación:

DataTemplateSelector en Xamarin.Forms
DataTemplateSelector en Xamarin.Forms

Podemos ver como aquellos monos que no cuentan con foto, además de no mostrarla, su nombre se encuentra alineado a la derecha.

Tenéis el código fuente disponible e GitHub:

Ver GitHub

Recordad que podéis dejar cualquier comentario, sugerencia o duda en los comentarios.

A tener en cuenta

Contamos con una serie de detalles y limitaciones a tener en cuenta:

  • En Android no podemos utilizar más de 20 plantillas por listado.
  • Un DataTemplateSelector no puede devolver otro.
  • El DataTemplateSelector no debe devolver una nueva instancia de cada DataTemplate en cada llamada, debería de usarse la misma.Cuidado con este punto si no deseamos obtener de forma sencilla Memory Leaks.

Más información

[Xamarin.Forms] Animaciones y nueva librería

AnimationIntroducción

En todas las plataformas, las aplicaciones móviles incluyen animaciones que otorgan movimiento, fluidez y focalizan la atención del usuario en las zonas deseadas. Actualmente no son un extra o añadido en las aplicaciones, sino una parte importante en la experiencia y usabilidad de las mismas.

Como desarrolladores, debemos no solo cuidar por supuesto el correcto funcionamiento de la aplicación, sino que debemos preocuparnos también por la usabilidad y la experiencia otorgada, donde entran en juego las animaciones.

En este artículo vamos a profundizar a fondo en el uso de animaciones desde Xamarin.Forms.

Animaciones en Xamarin.Forms

Xamarin.Foms incluye una serie de métodos de extensión que nos permiten realizar una completa gestión de animaciones desde código C#.

Por un lado tenemos disponibles una serie de animaciones predefinidas disponibles como métodos de extensión para elementos de tipo View. Contamos con animaciones para realizar rotaciones, escalados, tralaciones, etc. Los métodos de extensión a utilizar son:

  • FadeTo: Podemos animar la opacidad de un elemento visual.
  • RelRotateTo: Podemos especificar un ángulo de rotación para realizar transformaciones de rotación.
  • RelScaleTo: Transformación de escalado.
  • RotateTo: Transformación de rotación.
  • RotateXTo: Transformación de rotación.
  • RotateYTo: Transformación rotación.
  • ScaleTo: Transformación de escalado.
  • TranslateTo: Estableciendo las propiedades TranslationX y TranslationY podemos realizar traslaciones del elemento visual.

En caso de necesitar animaciones más complejas podemos utilizar las extensiones de animación. Contamos con varias sobrecargas del método Animate que nos permite definir animaciones más complejas.

Podemos crear un ejemplo sencillo donde probar tanto las animaciones predefinidas como las personalizadas. En la interfaz añadimos dos cuadrados (BoxView) con dos botones:

<StackLayout>
    <Label Text="Pre-defined Animations" />
    <BoxView
      x:Name="PreDefinedBox"
      HorizontalOptions="Center"
      VerticalOptions="Center"
      HeightRequest="125"
      WidthRequest="125"
      BackgroundColor="Red"/>
    <Button
      x:Name="PreDefinedButton"
      HorizontalOptions="Center"
      VerticalOptions="Center"
      Text="Animate"/>
    <Label Text="Custom Animations" />
    <BoxView
      x:Name="CustomBox"
      HorizontalOptions="Center"
      VerticalOptions="Center"
      HeightRequest="125"
      WidthRequest="125"
      BackgroundColor="Blue"/>
    <Button
      x:Name="CustomButton"
      HorizontalOptions="Center"
      VerticalOptions="Center"
      Text="Animate"/>
</StackLayout>

El primer botón animará la primera caja con animaciones predefinidas:

await PreDefinedBox.ScaleTo(2, 1000, Easing.CubicInOut);              
await PreDefinedBox.RotateTo(75, 1000, Easing.CubicInOut);                
await PreDefinedBox.ScaleTo(1, 1000, Easing.CubicInOut);

Realizamos un escalado al doble del tamaño, rotamos 75º y volvemos a escalar al tamaño original.

Sencillo, ¿verdad?

En caso de necesitar realizar animaciones personalizadas más complejas, podemos utilizar el método Animate:

CustomBox.Animate("Custom Animation", x => 
{
     CustomBox.BackgroundColor = Color.FromRgb(x, 0, 1 - x);
     CustomBox.Scale = 1 + 1.1 * x;                
}, length: 500);

Realizamos un cambio de color y escalado.

El resultado en ambos casos:

Animaciones en Xamarin.Forms
Animaciones en Xamarin.Forms

El ejemplo lo podéis encontrar en GitHub:

Ver GitHub

Xamanimation

Xamanimation es una librería destinada para Xamarin.Forms que tiene como objetivo facilitar el uso de animaciones a los desarrolladores. Añade un conjunto de animaciones de uso muy sencillo tanto desde código C# como desde código XAML.

Podemos definir animaciones en XAML a un elemento visual al cargar mediante un Behavior, usar un trigger en XAML para ejecutar la animación a voluntad al lanzar el trigger o bien desde código C#.

Animaciones disponibles

La librería cuenta una gran variedad de animaciones:

  • FadeTo
  • Flip
  • Heart
  • Jump
  • Rotate
  • Scale
  • Shake
  • Translate
  • Turnstile

Animando desde XAML

Una de las ventajas principales de la librería es la posibilidad de uso de animaciones desde XAML. Debemos utilizar el siguiente namespace:

xmlns:xamanimation="clr-namespace:Xamanimation;assembly=Xamanimation"

Al igual que en el ejemplo anterior, vamos a animar un cuadrado:

 <BoxView
     x:Name="FadeBox"
     HeightRequest="120"
     WidthRequest="120"
     Color="Blue" />

Tanto a nivel de recursos de aplicación como de vista, podemos definir animaciones:

<xamanimation:FadeToAnimation
     x:Key="FadeToAnimation"
     Target="{x:Reference FadeBox}"
     Duration="2000"
     Opacity="0"/>

Utilizando el namespace de xamanimation, tenemos acceso a todo el conjunto de animaciones disponible en la librería. En todas ellas hay una serie de parámetros comunes como:

  • Target: Nos permite indicar el elemento visual al que le aplicaremos la animación.
  • Duration: Duración de la animación en milisegundos.

Según el tipo de animación utilizada contaremos con más parámetros para personalizar la animación específica. Por ejemplo, en el caso de Fade contaremos con una propiedad Opacity para establecer como modificamos la opacidad.

Para lanzar la animación tenemos dos opciones:

  • Trigger: Llamado BeginAnimation que nos permite lanzar una animación al producirse una condición.
  • Behavior: Contamos con un Behavior llamado BeginAnimation que podemos asociar a un elemento visual de modo que que indicando la animación deseada, podemos lanzar la misma cuando se produzca la carga del elemento.

Utilizando el evento Clicked de un botón podemos lanzar la animación anterior utilizando el trigger facilitado por la librería:

<Button         
     Text="Fade">
     <Button.Triggers>
          <EventTrigger Event="Clicked">
               <xamanimation:BeginAnimation
                    Animation="{StaticResource FadeToAnimation}" />
          </EventTrigger>
     </Button.Triggers>        
</Button>

Sencillo, ¿cierto?. También contamos con el concepto de Storyboard como un conjunto de animaciones que podemos ejecutar a lo largo del tiempo:Animations 02

<xamanimation:StoryBoard
     x:Key="StoryBoard"
     Target="{x:Reference StoryBoardBox}">
       <xamanimation:ScaleToAnimation  Scale="2"/>
       <xamanimation:ShakeAnimation />
</xamanimation:StoryBoard>

El ejemplo anterior ejecutaría un escalado al doble del tamaño original y tras escalar realizaría una «agitación».

Animando desde C#

De igual forma que podemos utilizar las animaciones de la librería desde XAML, podemos hacerlo desde código C#. Contamos con un método de extensión llamado Animate que espera una instancia de cualquiera de las animaciones disponibles.

Si deseamos animar de nuevo un cuadrado llamado AnimationBox:

<BoxView
     x:Name="AnimationBox"
     HeightRequest="120"
     WidthRequest="120"
     Color="Blue" />

Bastará con acceder al elemento, utilizar el método Animate con la animación deseada:

AnimationBox.Animate(new HeartAnimation());

Podéis ver un subconjunto de las animaciones disponibles en acción a continuación:

Xamanimation
Xamanimation

El ejemplo lo podéis encontrar en GitHub:

Ver GitHub

Recordad que cualquier tipo de comentario, sugerencia o duda la podéis dejar en los comentarios de la entrada.

¿Y que esperar de la librería?

El código fuente esta disponible en GitHub y hay libertad absoluta para realizar con el lo que estiméis oportuno. Si deseáis colaborar, sin duda se aceptarán Pull Request. La librería seguirá evolucionando próximamente con:

  • Más opciones en cada animación (modo repetición)
  • Más animaciones (Color, Wobble, etc.)
  • Y otras novedades!

Más información

[Xamarin.Forms] Soporte a UWP

Universal Windows Platform

Windows 10 ha llegado como la culminación en el viaje hacia la convergencia en el desarrollo entre plataformas Windows. Ahora hablamos de Apps Universales
escritas una única vez con un código común tanto para la lógica de
negocio como para la interfaz de usuario. Además, generamos un único
paquete que mantendrá una interfaz consistente y familiar para el
usuario pero adaptada a cada plataforma.

Windows 10

Windows 10

Podemos crear apps que funcionen en todo tipo de
dispositivos como teléfonos, tabletas, portátiles, dispositivos IoT,
Surface Hub e incluso HoloLens. Para ello tenemos las vías utilizadas
hasta este momento, es decir, u
tilizando C# y XAML (o VB, C++, etc).

Xamarin.Forms 2.0

Con la llegada de Xamarin 4 han aterrizado una gran
cantidad de diversas novedades entre las que destaca la versión 2.0 de
Xamarin Forms. Entre las novedades principales contamos con:

  • Soporte a UWP.
  • Compilación de XAML (XAMLC).
  • Optimización en Layouts.
  • Optimización de listados. Incluidas nuevas estrategias de cacheo.
  • Corrección de bugs.

Añadiendo UWP a App Xamarin.Forms

Vamos a crear un proyecto Xamarin.Forms y le añadiremos soporte a UWP. Necesitaremos:

  • Visual Studio 2015
  • Windows 10
  • Xamarin.Forms 2.0

Creamos un nuevo proyecto Xamarin.Forms:

Nueva App Xamarin.Forms

Nueva App Xamarin.Forms

Sobre la solución hacemos clic derecho y seleccionamos la opción añadir nuevo proyecto. Dentro de la categoría Universal elegimos la plantilla en blanco.

Nueva Aplicación Universal

Nueva Aplicación Universal

Tras añadir el nuevo proyecto, continuaremos añadiéndolo el paquete NuGet de Xamarin.Forms 2.0 necesario.

Añadimos la referencia a la PCL.

Tenemos las referencias a la PCL y a Xamarin.Forms, ahora debemos
realizar pequeñas modificaciones en código para inicializar Xamarin
Forms y la aplicación. En el método OnLaunched de App.xaml.cs utilizaremos el método Init para inicializar Xamarin.Forms:

Xamarin.Forms.Forms.Init (e);

En las vista principal, MainPage.xaml modificamos el tipo de la página de Page a WindowsPage utilizando el namespace Xamarin.Forms.Platform.UWP.

xmlns:forms="using:Xamarin.Forms.Platform.UWP"

Por último, añadimos una llamada al método LoadApplication en el contructor de la vista principal, MainPage.xaml.cs para inicializar la aplicación.

LoadApplication(new UWP.App());

Tenéis el código fuente disponible e GitHub:

Ver GitHub

Recordad que podéis dejar cualquier comentario, sugerencia o duda en los comentarios.

Limitaciones

El soporte es bastante elevado pero no es aún completo. Existen una serie de limitaciones conocidas:

  • El aspecto de algunas páginas o elementos no esta cerrado.
  • Existe algún posible error en navegación.
  • No hay soporte aún a mapas.

Más información

[Tips and Tricks] Compilando XAML en Xamarin.Forms

Introducción

Data binding es un mecanismo mediante el cual
podemos enlazar los elementos de la interfaz de usuario con los objetos
que contienen la información a mostrar. Cuando realizamos data binding,
creamos una dependencia entre el valor de una propiedad llamada target con el valor de otra propiedad llamada source. Donde normalmente, la propiedad target recibirá el valor de la propiedad source.

En Xamarin.Forms es el mecanismo base que nos permite utilizar el
patrón MVVM. Sin embargo, el mecanismo no es perfecto, cuenta con
limitaciones, los errores de Binding no se producían en tiempo de
compilación de la App además de tener diferentes mejoras relacionadas
con el rendimiento.

Con la llegada de Xamarin.Forms 2.0 tenemos la posibilidad de compilar XAML.

XAMLC

Podemos compilar el XAML en lugar de ser interpretado (XAMLC). Las ventajas son múltiples:

  • Podemos detectar errores en marcado en tiempo de compilación.
  • Los tiempos de inicialización y carga se reducen.
  • Se reduce tamaño del ensamblado.

El compilado de XAML es una opción que por defecto viene deshabilitada con el objetivo de mantener con facilidad compatibilidad hacia atrás.

NOTA: En estos momentos XAMLC no es compatible con la plataforma Windows.

Podemos indicar que deseamos compilar una vista utilizando el atributo XamlCompilation a nivel de clase.

[XamlCompilation (XamlCompilationOptions.Compile)]

Le indicamos el valor XamlCompilationOptions.Compile. Si lo que queremos es compilar todas las vistas de una App, utilizaremos el prefijo assembly para el atributo XamlCompilation.

[assembly: XamlCompilation (XamlCompilationOptions.Compile)]

Todas las vistas incluidas en el namespace utilizado con el atributo quedarán afectadas.

Sencillo, ¿cierto?

Podéis acceder al código fuente directamente en GitHub:

Ver GitHub

Más información