[Xamarin.Forms] Aplicación móvil y Cosmos DB

Introducción

En una gran variedad de aplicaciones móviles se requiere almacenar datos. Podemos almacenar datos locales con opciones como SQLite o Realm; o en la nube con diferentes opciones. Entre las opciones disponibles en Azure, ha llegado con fuerza Cosmos DB.

En este artículo vamos a ver paso a paso como utilizar una base de datos de documentos Cosmos DB en una aplicación Xamarin.Forms. Realizaremos una aplicación que permita tomar, modificar y eliminar notas.

Cosmos DB

Una base de datos de documentos Azure Cosmos DB es una base de datos No SQL que proporciona acceso a información (JSON) de forma rápida, con alta disponibilidad, escalable y con replicación global.

Una base de datos de documentos en Azure Cosmos DB es un contenedor lógico para colecciones de documentos y usuarios. Puede contener cero o más colecciones. A su vez, cada colección de documentos puede tener un nivel de rendimiento diferente en base a la frecuencia de acceso. Cada colección de documentos cuenta con documentos JSON. A medida que se añaden documentos a una colección, Cosmos DB indexa automáticamente.

NOTA: Para pruebas y desarrollo, una base de datos de documentos se puede utilizar con un emulador. El emulador permite probar de forma local sin necesidad de suscripción Azure ni costes.

Crear Azure Cosmos DB

Accede al portal de Azure. Desde el menú lateral, Databases > Azure Cosmos DB:

Nueva Azure Cosmos DB

A continuación, debemos rellenar el formulario de creación:

Crear CosmosDB Azure

Donde:

  • API: Existen cuatro opciones diferentes: Gremlin (graph), MongoDB, SQL (DocumentDB), y tablas (key-value). En nuestro ejemplo usaremos DocumentDB.

Preparando el proyecto

Partiendo de una aplicación Xamarin.Forms, lo primero que necesitamos para realizar la integración con Azure Cosmos DB es añadir el paquete NuGet DocumentDB Client Library a la solución.

Microsoft.Azure.DocumentDB

La interfaz ded usuario

En nuestra aplicación contaremos con dos vistas, un listado de notas y una vista de detalles para crear, editar o eliminar una nota específica.

Comenzamos definiendo la vista principal. Tendremos un listado de notas:

<ListView 
     ItemsSource="{Binding Items}" 
     SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
     RowHeight="60">
     <ListView.ItemTemplate>
          <DataTemplate>
               <ViewCell>
                    <ViewCell.View>
                         <StackLayout 
                              Padding="12,0,12,0" 
                              HorizontalOptions="FillAndExpand">
                              <Label 
                                   Text="{Binding Notes}"
                                   FontSize="Medium"
                                   FontAttributes="Bold"/>
                              <Label 
                                   Text="{Binding Date}"
                                   FontSize="Small"/>
                         </StackLayout>
                     </ViewCell.View>
                </ViewCell>
           </DataTemplate>
      </ListView.ItemTemplate>
</ListView>

A parte de definir como se visualizará cada elemento de la lista definiendo el DataTemplate establecemos la fuente de información, propiedad ItemsSource enlazada a propiedad de la ViewModel que obtendrá los datos de la base de datos.

Además del listado, debemos añadir en nuestra interfaz una forma de poder insertar nuevas tareas. Para ello, una de las opciones más habituales e idóneas es utilizar una Toolbar.

 <ContentPage.ToolbarItems>
      <ToolbarItem
           Name="Add" 
           Command="{Binding AddCommand}">
           <ToolbarItem.Icon>
                <OnPlatform 
                     x:TypeArguments="FileImageSource"
                     Android="plus" 
                     iOS="plus.png" />
           </ToolbarItem.Icon>
      </ToolbarItem>
 </ContentPage.ToolbarItems>

La clase Device es muy importante en Xamarin.Forms ya que nos permite acceder a una serie de propiedades y métodos con el objetivo de personalizar la aplicación según dispositivo y plataforma. Además de permitirnos detectar el tipo de dispositivo, podemos detectar la plataforma gracias a la enumeración Device.OS o personalizar elementos de la interfaz gracias al método Device.OnPlatform entre otras opciones. En nuestro ejemplo, personalizamos el icono de añadir en base a la plataforma.

Nuestra interfaz:

Listado de notas

Enlazamos la View con la ViewModel estableciendo una instancia de la ViewModel a la propiedad BindingContext de la página.

BindingContext = App.Locator.NoteItemViewModel;

En la ViewModel contaremos con una propiedad pública para definir el listado de notas, además de la nota seleccionada (utilizada para la navegación):

private ObservableCollection<Note> _items;
private Note _selectedItem;

public ObservableCollection<Note> Items
{
     get { return _items; }
     set
     {
          _items = value;
          OnPropertyChanged();
     }
}

public Note SelectedItem
{
     get { return _selectedItem; }
     set
     {
          _selectedItem = value;
          _navigationService.NavigateTo<NoteItemViewModel>(_selectedItem);
     }
}

Añadimos elementos con un comando disponible en la ViewModel.

public ICommand AddCommand
{
     get { return _addCommand = _addCommand ?? new Command(AddCommandExecute); }
}

Al pulsar y lanzar el comando, navegaremos a la vista de detalles.

_navigationService.NavigateTo<NoteItemViewModel>(todoItem);

Si creamos un nuevo elemento pasaremos como parámetro una nueva entidad de tipo Note, en caso de seleccionar una existente, pasaremos el seleccionado disponible en la propiedad SelectedItem.

Definimos la interfaz de la vista de detalles:

<StackLayout 
     VerticalOptions="StartAndExpand" 
     Padding="20">
     <Label 
          Text="Notes" />
     <Entry 
          Text="{Binding Notes}"/>
     <Button 
          Text="Save"
          Command="{Binding SaveCommand}"/>
     <Button 
          Text="Delete"
          Command="{Binding DeleteCommand}"/>
     <Button 
          Text="Cancel"
          Command="{Binding CancelCommand}"/>
</StackLayout>

El resultado:

Detalles

Para enlazar la información de un elemento seleccionado, debemos capturar la información enviada en la navegación.

¿Cómo capturamos el elemento seleccionado en la navegación?. Utilizamos el método OnAppearing para capturar el parámetro NavigationContext.

public override void OnAppearing(object navigationContext)
{
     var note = navigationContext as Note;

     if (note != null)
     {
          Id = note.Id;
          Notes = note.Notes;
     }

     base.OnAppearing(navigationContext);
}

En cuanto a cada botón, cada uno de ellos estará enlazado a un comando:

private ICommand _saveCommand;
private ICommand _deleteCommand;
private ICommand _cancelCommand;

public ICommand SaveCommand
{
     get { return _saveCommand = _saveCommand ?? new Command(SaveCommandExecute); }
}

public ICommand DeleteCommand
{
     get { return _deleteCommand = _deleteCommand ?? new Command(DeleteCommandExecute); }
}

public ICommand CancelCommand
{
     get { return _cancelCommand = _cancelCommand ?? new Command(CancelCommandExecute); }
}

private void SaveCommandExecute()
{
 
}
 
private void DeleteCommandExecute()
{
 
}
 
private void CancelCommandExecute()
{
 
}

Consumiendo la base de datos Cosmos DB

Vamos a crear un servicio que contenga toda la lógica necesaria para trabajar con Cosmos DB desde nuestra aplicación Xamarin.Forms. DocumentClient encapsula la lógica necesaria relacionada con credenciales y conexiones con Azure Cosmos DB.

Comenzamos creando una instancia de DocumentClient:

var client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);

En el constructor del cliente debemos pasar tanto la URL de conexión como la clave primaria. Ambos valores se pueden obtener desde el portal de Azure.

Clave Primaria

Con el cliente preparado, tenemos todo lo necesario para trabajar con Azure Cosmos DB.

Creando base de datos

De las primeras acciones a realizar sera la creación de la base de datos. Recuerda, una base de datos de documentos es un contenedor lógico para colecciones de documentos. Podemos crearla tanto desde el portal Azure como por código. Utilizaremos el método CreateDatabaseIfNotExistsAsync:

await _client.CreateDatabaseIfNotExistsAsync(new Database
{
     Id = databaseName
});

El método crea la base de datos con el identificador establecido en Id o bien, devuelve la base de datos si ya existe. Se devuelve Task<ResourceResponse<Database>> que contiene un código de estado, ideal para verificar si la base de datos se ha creado o si se ha obtenido una previamente existente.

Crear colección de documentos

Una colección de documentos es un contenedor de documentos JSON. Al igual que la base de datos, podemos crearlo en el portal o por código. Por código utilizamos CreateDocumentCollectionIfNotExistsAsync:

 await _client.CreateDocumentCollectionIfNotExistsAsync(
      UriFactory.CreateDatabaseUri(databaseName),
      new DocumentCollection
      {
           Id = collectionName
      });

El método requiere dos parámetros obligatorios (también cuenta con otros opcionales):

  • Nombre de base de datos: Especificado como Uri.
  • DocumentCollection: Representa una colección de documentos. Especificamos el nombre utilizando la propiedad Id.

El método crea la colección si no existe o devuelve la colección si ya existía previamente.

Obtener documentos de una colección

El contenido de una colección se puede obtener ejecutando una consulta. Podemos crear consultas utilizando el método CreateDocumentQuery. Por ejemplo:

var query = _client.CreateDocumentQuery<T>(_collectionLink) 
     .AsDocumentQuery();

while (query.HasMoreResults)
{
     items.AddRange(await query.ExecuteNextAsync<T>());
}

De esta forma podemos obtener todos los documentos de una colección específica. En el método CreateDocumentQuery se puede especificar vía Uri la colección de datos a la que conectar.

El método AsDocumentQuery convierte el resultado de la creación de la consulta en un objeto de tipo IDocumentQuery<T>. ExecuteNextAsync vamos obteniendo los resultados de la siguiente página (mientras exista más valores HasMoreResults).

Crear documento

Crear documentos cuyo contenido es en formato JSON se pueden insertar en una colección utilizando CreateDocumentAsync:

await _client.CreateDocumentAsync(_collectionLink, item);

Se especifica vía Uri la colección en la que se va a insertar el documento y el argumento de tipo objeto. El objeto es la información a insertar.

Eliminar documento

Se pueden eliminar documentos utilizando DeleteDocumentAsync:

await _client.DeleteDocumentAsync(UriFactory.CreateDocumentUri(DatabaseName, CollectionName, id));

Se especifica vía Uri el documento de la colección a eliminar.

NOTA: También es posible eliminar toda una colección de documentos con DeleteDocumentCollectionAsync e incluso una base de datos completa con DeleteDatabaseAsync.

Llegados a este punto, ¿qué nos falta?. Sencillo, utilizar la lógica para interactuar con Azure Cosmos DB desde nuestras ViewModels. Crearemos la base de datos y la colección al navegar a la primera vista. En esta primera vista obtendremos todos los documentos creados (nuestras notas!). Desde la vista de detalles, en cada comando enlazado a la interfaz, utilizaremos la lógica para crear o eliminar notas.

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

Ver GitHubTe animo a descargar el ejemplo y realizar tus propias pruebas. Hasta aquí llegamos!. Recordad que podéis dejar cualquier comentario, sugerencia o duda en los comentarios.

Más información

[Evento online] Trucos y consejos rendimiento Xamarin.Forms

Introducción

Recientemente, en SVQXDG, tuvimos un interesante evento Xamarin relacionado con el rendimiento en Xamarin.Forms. Tras recibir feedback por diferentes redes sociales, meetup o vía correo, ante el interés en diferentes partes geográficas hemos decidido…repetir el evento online!

El evento

¿Sabes el ciclo de vida de un Layout?, ¿qué opciones de Layout son más óptimas?, ¿cómo afectan los Bindings al rendimiento y como tratarlos?, ¿rendimiento en listados?, ¿fast renderers?. A todas esas preguntas y a otras tantas, intentaremos dar solución en esta sesión online!.

El evento será el próximo Sábado, 17 de Junio a las 12:00h (GMT+1).

¿Te apuntas?

Más información

[Material] Rendimiento en Xamarin.Forms

Introducción

En Xamarin.Forms, ¿sabes el ciclo de vida de un Layout?, ¿qué opciones de Layout son más óptimas?, ¿cómo afectan los Bindings al rendimiento y como tratarlos?, ¿rendimiento en listados?, ¿fast renderers?. A todas esas preguntas y a otras tantas, intentamos dar respuesta en el último evento de SVQXDG celebrado el pasado 24 de Mayo.

El material

La presentación:

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

Ver GitHubGracias a todos los asistentes al evento. En esta ocasión me ha sorprendido la enorme cantidad de feedback y peticiones relacionados con esta sesión. Pronto se anunciará su repetición en esta ocasión online!

Nos vemos en la próxima!

Más información

[Xamarin.Forms] Forms Embedding

Introducción

Cuando tratamos el desarrollo de aplicaciones Xamarin hay algunas preguntas importantes a resolver. Entre ellas, destaca con fuerza, ¿Xamarin Classic o Xamarin.Forms?. Es una pregunta habitual en diferentes charlas de diferentes temáticas, en formación y a la hora de afrontar un nuevo proyecto. La respuesta suele requerir algo de tiempo para analizar muchos aspectos como la interfaz de la aplicación, conocimiento del equipo, etc. Pero…¿y si nos quedamos con las dos opciones?.

¿Qué es Forms Embedding?

Con Xamarin.Forms podemos acceder a cualquier API nativa, podemos crear nuevos controles y acceder a la plataforma con Custom Renders o efectos e incluso podemos incrustar controles nativos con Native Views. Forms Embedding es el nombre asignado a la posibilidad de incrustar cualquier ContentPage de Xamarin.Forms en una aplicación nativa de Android, iOS o Windows.

Forms Embedding

Estará disponible entre el conjunto de novedades de la próxima versión 3.0 de Xamarin.Forms:

  • Mejoras en rendimiento (Fast Renderers y Layout Compression).
  • Nuevas plataformas (GTK#, WPF o MacOS).
  • Native Embedding.
  • XAML Standard.
  • Etc.

Suena interesante, ¿verdad?. Aquellos desarrollos utilizando Xamarin Classic (también llamado Native) se pueden beneficiar de Xamarin.Forms para compartir vistas comunes. Podemos combinar lo mejor de las dos opciones!

Haciendo Forms Embedding ahora

A pesar de llegar como opción en Xamarin.Forms 3.0, podemos hacer Forms Embedding ahora mismo. Sólo necesitamos un poco más de código. Veamos como hacerlo!

Creamos una aplicación Xamarin Classic utilizando una PCL y la plantilla Maestro y detalle:

Nueva App

Gracias a la plantilla tenemos rápidamente una aplicación Xamarin Classic completa:

Plantilla Maestro y detalle

Añadimos un nuevo proyecto, una librería portable (PCL) donde vamos a añadir las vistas Xamarin.Forms totalmente compartidas entre todas las plataformas.

PCL

Un ejemplo muy común de vista que suele tener mucho sentido tener totalmente compartida, es una vista de configuración. Añadimos una nueva ContentPage llamada SettingsView:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FormsEmbedding.Forms.Views.SettingsView">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="Welcome to Xamarin Forms Settings!" />
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Label Grid.Column="0" Grid.Row="0" Text="Settings 1" />
                <Switch Grid.Column="1" Grid.Row="0" HorizontalOptions="End" />
                <Label Grid.Column="0" Grid.Row="1" Text="Settings 2" />
                <Switch Grid.Column="1" Grid.Row="1" HorizontalOptions="End" />
                <Label Grid.Column="0" Grid.Row="2" Text="Settings 3" />
                <Switch Grid.Column="1" Grid.Row="2" HorizontalOptions="End" />
                <Label Grid.Column="0" Grid.Row="3" Text="Settings 4" />
                <Switch Grid.Column="1" Grid.Row="3" HorizontalOptions="End" />
                <Label Grid.Column="0" Grid.Row="4" Text="Settings 5" />
                <Switch Grid.Column="1" Grid.Row="4" HorizontalOptions="End" />
            </Grid>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

El resultado:

SettingsView

¿Cómo utilizamos esta página desde Android, iOS y Windows?. Lo primero es crear una aplicación Application de tipo Xamarin.Forms.

public class FormsApp : Application
{
     public FormsApp(Type page = null)
     {
         SetMainPage(page);
     }

     public void SetPage(Type page)
     {
         if (page == null) 
         {
             MainPage = new ContentPage();
             return;
         }

         MainPage = (Page)Activator.CreateInstance(page);
     }

     public static Page GetPage<T>() where T : Page 
     {
         return Activator.CreateInstance<T>();
     }
}

Establecemos como MainPage la página pasada como parámetro.

Android

Xamarin.Forms utiliza una actividad de tipo FormsAppCompatActivity donde se realiza la inicialización de Xamarin.Forms y se realiza la carga de la App. Vamos a crear una actividad nueva donde realizar la inicialización requerida de Forms así como,  recibir la vista Xamarin.Forms a mostrar y cargarla en la App.

public class FormsActivity : FormsAppCompatActivity
{
     public static bool IsFormsInitialized;

     protected override void OnCreate(Bundle bundle)
     {
         base.OnCreate(bundle);

         var view = Intent.Extras.GetString("View");
         var viewPath = typeof(FormsApp).Namespace + ".Views." + view;
         var viewType = typeof(FormsApp).Assembly.GetType(viewPath);

         if (!IsFormsInitialized)
         {
             global::Xamarin.Forms.Forms.Init(this, bundle);
             IsFormsInitialized = true;
         }

         LoadApplication(new FormsApp(viewType));
     }
}

Fíjate que esperamos un parámetro View donde tenemos el nombre de la página Xamarin.Forms a mostrar. Partiendo del nombre, obtenemos el tipo de la página y realizamos la inicialización.

Con todo esto, posiblemente tengas ya en mente como vamos a realizar la navegación a la página de Xamarin.Forms:

var intent = new Intent(this, typeof(FormsActivity));
intent.PutExtra("View", "SettingsView");
StartActivity(intent);

Navegamos a una nueva actividad, nuestra actividad FormsActivity, pasandole como parámetro la página Xamarin.Forms a mostrar.

El resultado:

Android

 

iOS

En el caso de iOS nuestro objetivo será tener un UIViewController al que poder navegar partiendo de la ContentPage de Xamarin.Forms:

var settingsViewControler = FormsApp.GetPage<SettingsView>().CreateViewController();
await PresentViewControllerAsync(settingsViewControler, true);

En Xamarin.Forms contamos con una extensión de páginas que cuenta con el método CreateViewController que nos hace la mayor parte del trabajo. Obtenemos la página de Forms, convertimos a UIViewController y navegamos!

iOS

Windows

Llegamos a UWP. En este caso, Xamarin.Forms, utiliza una vista nativa de tipo FormsWindowsPage donde se realiza la carga de la App. Creamos en el proyecto UWP una nueva página nativa:

<forms:WindowsPage
    x:Class="FormsEmbedding.UWP.Pages.FormsWindowsPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:FormsEmbedding.UWP.Pages"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:forms="using:Xamarin.Forms.Platform.UWP"
    mc:Ignorable="d">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    </Grid>
</forms:WindowsPage>

Reemplazamos el tipo de Page a FormsWindowsPage utilizando el namespaces correspondiente. En el código asociado de la página realizaremos dos acciones necesarias (como ya hicimos en otras plataformas). Por un lado, inicializaremos la aplicación Xamarin.Forms:

var formsApp = new FormsApp()
LoadApplication(formsApp);

Y por otro lado, estableceremos la página principal:

_formsApp.SetPage(e.Parameter as Type);

Con todo preparado, para navegar a una página de Xamarin.Forms bastaría con:

Frame.Navigate(typeof(FormsWindowsPage), typeof(SettingsView));

Navegar a la nueva página creada pasando como parámetro el tipo de la página de Forms. También podríamos pasar el nombre de la página como cadena y tras recuperarlo obtener el tipo como hicimos en Android.

El resultado:

UWP

NOTA: En todos los proyectos nativos hemos añadido la última versión del paquete estable de Xamarin.Forms.

El ejemplo de esta versión se encuentra disponible en GitHub:

Ver GitHub

Xamarin.Forms 3.0

Hoy día ya podemos probar una versión Preview de Xamarin.Forms 3.0. Para ello, debemos añadir https://www.myget.org/F/xamarinforms-dev/api/v3/index.json como nuevo origen de paquetes.

Nuevo origen de paquetes

De esta forma tendrás acceso a los paquetes previos de Xamarin.Forms 3.0:

Paquetes NuGet Xamarin.Forms 3.0

Con el paquete previo de la versión 3.0 nos llega el soporte oficial a Forms Embedding o lo que es lo mismo, todo  lo necesario para incrustar páginas Xamarin.Forms en aplicaciones nativas de forma rápida y muy sencilla.

Volvemos a crear un nuevo proyecto en una PCL donde vamos a añadir las páginas Xamarin.Forms a compartir, de igual forma a como hicimos previamente.

Veamos como utilizar la página en cada plataforma.

Android

En Android se ha añadido una extensión de página de modo que podemos hacer:

var settings = new SettingsView().CreateFragment(this);

Creamos una instancia de la página Xamarin.Forms y utilizamos el método CreateFragment para crear un Fragment Android que podemos añadir como contenido de nuestra aplicación Xamarin.Android.

iOS

En el caso de iOS nuestro objetivo será tener un UIViewController al que poder navegar partiendo de la ContentPage de Xamarin.Forms:

var settingsViewControler = FormsApp.GetPage<SettingsView>().CreateViewController();
await PresentViewControllerAsync(settingsViewControler, true);

En Xamarin.Forms contamos con una extensión de páginas que cuenta con el método CreateViewController que nos hace la mayor parte del trabajo. Si, es sumamente parecido a lo que ya vimos previamente.

Windows

Y llegamos a UWP donde al igual que en el resto de plataformas, se utiliza una extensión de página para obtener un FrameworkElement a partir de la página Xamarin.Forms.

var settingsView = new SettingsView().CreateFrameworkElement();

Muy muy sencillo, ¿cierto?.

El ejemplo de esta versión se encuentra disponible en GitHub:

Ver GitHub

Más información

[Evento SVQXDG] Rendimiento en Xamarin.Forms

El evento

Continuamos desde SVQXDG con otro nuevo evento. En esta ocasión un tema muy tratado en diferentes quedadas y mencionado en eventos pero nunca hemos profundizado hasta ahora, el rendimiento en Xamarin.Forms.

¿Sabes el ciclo de vida de un Layout?, ¿qué opciones de Layout son más óptimas?, ¿cómo afectan los Bindings al rendimiento y como tratarlos?, ¿rendimiento en listados?, ¿fast renderers?. A todas esas preguntas y a otras tantas, intentaremos dar solución en esta sesión!.

La fecha

El evento tendrá lugar el próximo Miércoles, 24 de Mayo de 19:00h a 20:30h. Tendremos una única sesión técnica de 90 minutos de duración. Además contaremos con algún detalle entre los asistentes.

¿Te apuntas?

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, Aula B1.32
Av. Reina Mercedes s/n
Sevilla Se 41012

ETS de Ingeniería Informática

Más información

Xamarin Forms FastRenderers

Introducción

Recientemente se liberaba la versión 2.3.5 de Xamarin.Forms donde entre las diferentes novedades, destaca la aparición de FastRenderers y la mejora de rendimiento. Por ahora, sólo disponible en Android e incluido en los controles Label, Button, Frame e Image. Pero.. ¿qué son los Fast Renderers?, ¿por qué se habla de mejora de rendimiento?.

Fast Renderers

Hablamos de cambios realizados en Xamarin.Forms con el objetivo de reducir a mínimos de operaciones y cálculos a realizar para renderizar el control y gestionar su tamaño y posición.

FastRenderers

Por un lado se ha simplificado notablemente el conjunto de clases implicadas para realizar los cálculos necesarios para el renderizado, tamaño y posición. Previamente, un Label en Xamarin.Forms al ejecutarse en Android realizaba:

Ahora:

Se reduce el número de participantes llegando de forma mucho más directa al renderizado. Se sigue implementando la interfaz IVisualElementRenderer que permite tener los métodos OnElementChanged y OnElementPropertyChanged.

Hasta este punto, a pesar de reducir piezas en la lógica, no se ve una reducción drástica en el ciclo del Layout. También se han realizado importantes modificaciones en el ciclo del Layout. Previamente:

  • OnLayout de la clase LabelRenderer
    • OnLayout de ViewRenderer
    • MeasureAndLayout de ViewRenderer
      • OnLayout de VisualElementRenderer
        • UpdateLayout del control

Ahora:

  • On Layout de la clase LabelRenderer
    • OnLayout View

Además, mientras que antes todos los parámetros del Layout se actualizaban (OJO: Opacity, Rotation, Scale, etc) ahora se establecen todas una vez. Tambien se añaden validaciones para evitar refrescos del Layout innecesarios (Invalidate).

NOTA: Se mantienen también los renderers anteriores de los controles Label, Image, Frame y Button por compatibilidad hacia atrás.

Comparativa de rendimiento

Dependiendo del Layout y controles utilizados en la aplicación, la mejora de rendimiento se notará en mayor o menor medida. Hablamos desde un pequeño porcentaje hasta en según que ocasiones practicamente duplicar el rendimiento.

Para profundizar en este aspecto, vamos a crear un ejemplo con dos pruebas. Realizaremos una prueba básica donde tendremos una vista con 50 Buttons y 50 Labels. Recuerda, actualmente se han añadido FastRenderers de ButtonRenderer, FrameRenderer, LabelRenderer y ImageRenderer. La segunda prueba será un listado con cientos de elementos donde la plantilla que define cada fila utilizará un control de tipo Image, y dos Labels.

El ejemplo se encuentra disponible en GitHub:

Ver GitHub

Se utiliza Stopwatch para realizar medidas de tiempo de renderizado además de pruebas con la experiencia al hacer scroll en el listado, etc. Cambiando el paquete de Xamarin.Forms de versiones previas a la versión 2.3.5 o superior podemos hacer diferentes comparativas. Se aprecian mejores resultados en los tiempos (946ms > 708ms en el ejemplo básico). Te animo a descargar el ejemplo y a realizar tus propias medidas.

No cabe duda que en futuras versiones de Xamarin.Forms nos esperan más y más renderers utilizando FastRenderers lo que al final, nos afecta como desarrolladores, en una ganancia de rendimiento sin necesidad de trabajo extra.

Más información

[Xamarin.Forms] Un vistazo a Grial UI Kit V2

Introducción

Xamarin.Forms ofrece una capa de abstracción sobre la capa de la interfaz de usuario permitiendo definir la interfaz de usuario una única vez con código C# o XAML.

Desde los inicios de Xamarin.Forms a hoy día, todo ha evolucionado a pasos agigantados tanto las propias posibilidades de Xamarin.Forms, como el crecimiento de la comunidad así como la implicación de terceros. Hoy precisamente nos vamos a centrar en la segunda versión de Grial UI Kit.

NOTA: Gracias a los chicos de UXDivers por ceder una licencia de Grial para realizar pruebas sobre la librería.

Grial UI Kit

El objetivo principal de Grial es ofrecer un conjunto de controles y plantillas para Xamarin.Forms permitiendo crear interfaces de usuario ricas y vistosas con facilidad.

Grial UI Kit

Cuenta con soporte para:

  • Android 4.1+ (API Level 16).
  • iOS 8.0+.

Incluye:

  • Plantillas y vistas preparadas
  • Controles
  • Efectos
  • Animaciones
  • Temas
  • Iconos

Novedades

De la versión anterior a ahora se han añadido nuevas plantillas de páginas, nuevos controles, tres nuevos temas, animaciones y soporte a tabletas.

Creación de proyectos

La primera de las novedades visibles que vemos esta relacionada con la creación de proyectos. Accedemos a un portal de administración llamado Grial Admin.

Desde el panel de administración podemos crear aplicaciones añadiendo el nombre. De esta forma podemos descargar dos tipos de proyectos:

  • Full: Contiene absolutamente todos los ejemplos y controles incluidos en Grial.
  • Starter: Proyecto mínimo que cuenta con soporte a Grial, sus librerías.

Ambos cuentan con el espacio de nombres y todo lo necesario ya preparado con el nombre asignado a la aplicación.

Tras descargar el proyecto, debemos configurar el acceso a los paquetes NuGet añadiendo un nuevo repositorio de paquetes.

En Visual Studio, accedemos al menu de Opciones > Herramientas > Nuget Package Manager > Package Sources.

Nuevos paquetes

NOTA: Para configurar el repositorio será necesario introducir usuario y contraseña.

Optimización a Tablets

Una de las novedades más importantes se encuentra en las posibilidades de adaptación a diferentes factores de forma, teléfonos y tabletas.

UIs adaptadas a tabletas

Además de tener plantillas ya preparadas para funcionar correctamente tanto en teléfonos como tabletas, se añade un unos helpers Responsive.

Este helper cuenta con diferentes propiedades:

  • Default: Aplica a todos los casos. Es el valor por defecto.
  • Portrait: Aplica a todos los dispositivos en modo vertical.
  • Landscape: Aplica a todos los dispositivos en modo horizontal.
  • PortraitPhone: Aplica solo a teléfonos en modo vertical.
  • PortraitTablet: Aplica solo a tabletas en modo vertical.
  • PortraitDesktop: Aplica solo cuando el dispositivo es escritorio en modo vertical.
  • LandscapePhone: Aplica en teléfonos en modo horizontal.
  • LandscapeTablet: Aplica en tabletas en modo horizontal.
  • LandscapeDesktop: Aplica en escritorio en modo horizontal.

Su uso:

<Label
    Text="{ 
        artina:OnOrientationString 
            Portrait=IsPortrait, 
            Landscape=IsLandscape
        }" 
    IsVisible="{ 
        artina:OnOrientationBool 
            Default=true, 
            PortraitDesktop=false 
        }"
        "/>

El texto mostrará un texto diferente en modo vertical y horizontal además, siempre será visible menos en modo vertical en escritorio. Añade de forma sencilla bastante versatilidad para adaptar la interfaz de usuario en diferentes modos.

Temas

Se añaden varios temas ya preparados y tareas de compilación que permiten cambiar temas al vuelo en la aplicación.

Temas

Nuevos controles

Se han añadido nuevos controles:

  • TabControl: Control de pestañas compatible con iOS y Android que permite el posicionamiento tanto superior como inferior. Totalmente personalizable.
  • Badge: Icono numérico.
  • CircleIcon: Imagen circular.
  • Timeline: Listado con formato línea del tiempo.
  • Rating: Control para puntuar con estrellas.
  • Repeater: Control de listados con personalización de scroll, tamaño de elementos, etc.
  • Walkthroughs: Crea facilmente asistentes personalizables.
  • FontIcons: Permite mostrar iconos utilizando fuente. Incluidos más de 1500 iconos.
  • Lottie Animations: Se incluye soporte a animaciones Lottie.

TabControl

Analizando Grial

Tras ver novedades principales, vamos a continuar realizando un pequeño análisis de la librería.

El tamaño del paquete

Grial se basa en un conjunto de diferentes librerías.

PCL

  • UXDivers.Artina.Shared.dll (50KB)
  • UXDivers.Artina.Shared.Base.dll (13KB)

iOS

  • UXDivers.Artina.Shared.iOS.dll (19KB)
  • UXDivers.Artina.Shared.Base.iOS.dll (12KB)

Android

  • UXDivers.Artina.Shared.Droid.dll (31KB)
  • UXDivers.Artina.Shared.Base.Droid.dll (14KB)

Para utilizar los efectos tenemos otra librería:

PCL

  • UXDivers.Effects.dll (7KB)

iOS

  • UXDivers.Effects.iOS.dll (8KB)

Android

  • UXDivers.Effects.Droid.dll (93KB)

Y para controles:

PCL

  • UXDivers.Artina.Shared.Tab.dll (20KB) – Control TabControl
  • UXDivers.Artina.Shared.Repeater.dll (17KB) – Control Repeater

Dependencias

Con el firme objetivo de mejorar el rendimiento se han añadido algunas dependencias con librerías de terceros con respecto a la versión anterior. Nos encontramos con:

El XAML aportado en el proyecto PCL no está muy acoplado, sólo con los estilos definidos en App.xaml. En el proyecto Xamarin.Android, tenemos una personalización de temas nativos. Mientras que en el proyecto Xamarin.iOS, esta personalización de temas viene en forma de un archivo ThemeColors.cs.

Rendimiento

Grial hace uso de compilación de XAML, reutilización de celdas en listados y otras características incluidas en Xamarin.Forms centradas en el rendimiento. Tras hacer pruebas en emuladores y dispositivos haciendo medidas con Xamarin Profiler, no se encuentran problemas ni penalizaciones relacionadas con el rendimiento.

MVVM

Las páginas con diferentes plantillas, layouts y controles se encuentran asociadas a una ViewModel. La implementación del patrón así como la separación de responsabilidades se encuentra bien implementada ayudando a su correcta implementación al utilizar Grial. Los controles añadidos como por ejemplo el TabControl, añaden propiedades de dependencia necesarias para controlar el comportamiento y apariencia del control.

Soporte multiplataforma

Contamos con soporte a iOS y Android. Tras múltiples pruebas en diferentes dispositivos y emuladores nos encontramos con interfacecs robustas con una implementación prácticamente exacta en cada plataforma y condición.

No encontramos eso sí soporte a UWP (Universal Windows Platform). Es una plataforma que permite el acceso a los diferentes dispositivos de familias de Windows 10 (PCs, tabletas, teléfonos, Xbox One, Surface Hub, IoT, HoloLens).

Conclusiones

Volvemos a estar frente a un paquete bastante grande de plantillas con vistas muy comunes y necesarias en muchas aplicaciones (vista detalle de producto, sign in, registro, chat, configuración, etc.) con un diseño muy cuidado y adaptado a diferentes plataformas y factores de forma. En esta versión nos encontramos la adaptación a diferentes factores de forma, el uso de temas o la llegada de nuevos controles.

Un componente  que no solo aporta funcionalidad, también la forma de hacer ciertas necesidades en la UI con Xamarin.Forms.

¿Y a ti que te parece?

Más información

[Xamarin] Gráficas con Oxyplot

ChartIntroducción

En ocasiones en nuestras aplicaciones tendremos la necesidad de mostrar al usuario cierta información de la manera más directa y sencilla posible de modo que de un solo vistazo el usuario sea capaz de obtener la mayor información posible. A nivel de interfaz tenemos muchísimas opciones muy interesantes sin embargo, un excelente recurso muy utilizado para este tipo de situaciones es el uso de gráficas. Por ejemplo, estamos realizando una aplicación de compra de viviendas. Sería fantástico mostrarle al usuario la información de como ha oscilado el precio de la viviendo en el último trimestre por ejemplo. ¿Como lo hacemos?, ¿Que piensas que sería lo más acertado?. Posiblemente una gráfica de barras u otra similar te haya pasado por la mente.

En esta entrada vamos a aprender como utilizar gráficas en nuestras aplicaciones Xamarin utilizando OxyPlot.

Añadiendo las dependencias necesarias

Tras crear la solución Xamarin.Forms, comenzamos añadiendo las dependencias necesarias. Hacemos clic secundario sobre la solución, Administrar paquetes NuGet para la solución…

Añadir paquetes NuGet

Buscamos por Oxyplot.Xamarin.Forms:

Oxyplot.Xamarin.Forms

Inciando renderers Oxyplot

Es necesario añadir código específico en cada plataforma para inicializar renderers de Oxyplot.

iOS

Utilizamos el método FinishedLaunching del delegado de la aplicación:

OxyPlot.Xamarin.Forms.Platform.iOS.PlotViewRenderer.Init();

Android

En el método OnCreate de la actividad principal debemos añadir:

OxyPlot.Xamarin.Forms.Platform.Android.PlotViewRenderer.Init();

Windows

En este caso, en la clase App.xaml.cs, donde se define Application en Windows, utilizamos el método OnLaunched:

OxyPlot.Xamarin.Forms.Platform.UWP.PlotViewRenderer.Init();

PlotView

Tras inicializar OxyPlot, estamos preparados para comenzar a trabajar con la librería. OxyPlot cuenta con un control llamado PlotView. Este control se encuentra disponible en el namespace XAML:

xmlns:oxyplot="clr-namespace:OxyPlot.Xamarin.Forms;assembly=OxyPlot.Xamarin.Forms"

El control cuenta con una propiedad fundamental Model de tipo PlotModel:

<AbsoluteLayout>
     <oxyplot:PlotView
          AbsoluteLayout.LayoutFlags="All"
          AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
          Model="{Binding PlotModel}" />
</AbsoluteLayout>

PlotModel define el origen de la fuente de información de la gráfica así como, información relacionada con el tipo de gráfica.

Enlazar datos

A nivel de ViewModel, necesitamos definir una propiedad de tipo PlotModel:

private PlotModel _plotModel;

Propiedad pública:

public PlotModel PlotModel
{
     get { return _plotModel; }
     set
     {
          _plotModel = value;
          RaisePropertyChanged();
     }
}

PlotModel cuenta con diferentes propiedades que permiten definir el renderizado de la gráfica. Tenemos desde propiedades sencillas y comunes como Title que permite definir el título de la gráfica a otras más complejas como Series.

La propiedad Series espera un valor de tipo OxyPlot.Series. Esta propiedad permite definir el tipo de gráfica a utilizar.

Veamos un sencillo ejemplo para crear una gráfica de columnas utilizando ColumnSeries:

PlotModel = new PlotModel
{
     Title = "Column"
};

var columnSerie = new ColumnSeries
{
     StrokeThickness = 2.0
};

columnSerie.Items.Add(new ColumnItem(1));
columnSerie.Items.Add(new ColumnItem(2));
columnSerie.Items.Add(new ColumnItem(3));
columnSerie.Items.Add(new ColumnItem(4));
columnSerie.Items.Add(new ColumnItem(5));

PlotModel.Series.Add(columnSerie);

El resultado:

Gráfica de columnas

Tipos de gráficas

Tenemos una enome variedad de tipos de gráficas diferentes:

  • Área
  • Líneas
  • Barras
  • Columnas
  • Puntos
  • Circular
  • Mapa de calor
  • Etc

Además se pueden realizar composiciones haciendo combinaciones de varias de ellas, por ejemplo, barras con líneas.

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

Ver GitHub

Recuerda, cualquier tipo de duda o sugerencia es bienvenida en los comentario del artículo.

Más información

[Xamarin.Forms] Uso de Mapas básico con MVVM

mapsIntroducción

En el desarrollo de aplicaciones móviles contamos con una serie de controles de peso, altamente utilizados y que definen las características básicas de muchas aplicaciones. Hablamos de controles como listados, carruseles o mapas.

En Xamarin.Forms se pueden utilizar mapas utilizando las APIs nativas de cada plataforma. El uso básico se ve altamente simplifcado utilizando un paquete NuGet, Xamarin.Forms.Maps, que requiere cierta configuración inicial.

Trabajando con mapas, el inicio

Para trabajar con mapas en Xamarin.Forms debemos de comenzar añadiendo un paquete NuGet en cada proyecto de la solución, es decir, tanto en la librería portable como en cada proyecto nativo.

NuGet

NuGet

Tras añadir el paquete NuGet se deben de realizar tareas de inicialización.

En el caso de iOS se debe añadir:

Xamarin.FormsMaps.Init();

En el delegado principal de la aplicación tras inicializar Xamarin.Forms en el método FinishedLaunching.

En el caso de Android:

Xamarin.FormsMaps.Init(this, bundle);

Se realiza la inicialización de los mapas en la actividad principal utilizando el método OnCreate.

Por último, en el caso de Windows, la inicialización se realiza en el constructor de la página principal, MainPage:

Xamarin.FormsMaps.Init("INSERT_AUTHENTICATION_TOKEN_HERE");

Además de realizar el proceso de inicialización, los mapas requieren de ciertas capacidades además de requerir un Api Key correspondiente a los mapas nativos utilizados en cada plataforma.

En iOS, si se utiliza iOS 8 o superior, es necesario añadir dos claves al Info.plist.

<key>NSLocationAlwaysUsageDescription</key>
    <string>Can we use your location</string>
<key>NSLocationWhenInUseUsageDescription</key>
    <string>We are using your location</string>

En Android se utiliza la API de Google Maps que requiere un Api Key. A nivel de aplicación en el arhivo de manifiesto Android es necesario añadir:

<meta-data android:name="com.google.android.maps.v2.API_KEY"
            android:value="INSERT_API_KEY" />

Además, es necesario añadir los siguientes permisos:

  • AccessCoarseLocation
  • AccessFineLocation
  • AccessLocationExtraCommands
  • AccessMockLocation
  • AccessNetworkState
  • AccessWifiState
  • Internet

Se pueden añadir desde Opciones > Build > Android Application.

Para trabajar con Windows, como ya vimos en el proceso de inicialización, se necesita generar un token de autorización para poder autenticar con Bing Maps.

Uso básico de mapas

A la hora de trabajar con mapas en Xamarin.Forms haremos uso del control Map. El control se puede inicializar y utilizar desde C#:

var map = new Map(
            MapSpan.FromCenterAndRadius(
                   new Position(37,-122), Distance.FromMiles(0.3))) {
                   IsShowingUser = true,
                   HeightRequest = 100,
                   WidthRequest = 960,
                   VerticalOptions = LayoutOptions.FillAndExpand
            };

Y desde XAML:

  <maps:Map 
       x:Name="MyMap"
       WidthRequest="320" 
       HeightRequest="200" />

Donde el namespace XAML es:

xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"

Las propiedades fundamentales del mapa son:

  • MapType: Permite establecer el tipo de mapa entre vista satélite, calle e híbrida.
  • Pins: Conjunto de pushpins del mapa.

Para añadir pushpins al mapa basta con rellenar la colección Pins con objetos de tipo Pin.

En cuanto a los métodos fundamentales tenemos:

  • MoveToRegion: Permite establecer y modificar la posición y nivel de zoom aplicado al mapa.
MyMap.MoveToRegion(
    MapSpan.FromCenterAndRadius(
      new Position(37,-122), Distance.FromMiles(1)));

Utilizando MVVM

Hasta este punto tenemos el mapa funcionando y contamos con todos los conceptos básicos necesarios para trabajar con mapas. Sin embargo, rellenar la colección de pushpins utilizando la propiedad Pins o posiciona el mapa utilizando el método MoveToRegion en el código asociado, no es lo que habitualmente realizamos.

¿Cómo utilizamos todo utilizando MVVM?

Pongámonos en situación. Habitualmente tendremos cierto contexto. Imagina que tenemos una aplicación de Taxis donde por supuesto, tendremos clientes. Cada cliente lo representaremos utilizando una entidad, dentro de la carpeta Models:

    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
        public string Description { get; set; }
        public double Longitude { get; set; }
        public double Latitude { get; set; }
        public DateTime? FullyAttendedTime { get; set; }
    }

La lógica necesaria para añadir pushpins al mapa es sencilla utilizando la propiedad Pins del mapa. También podemos gestionar la posición central del mapa y el nivel de zoom utilizando el método MoveToRegion:

private void AddPins()
{
     foreach (var customer in DataRepository.LoadCustomerData())
     {
                var pin = new Pin
                {
                    Type = PinType.Place,
                    Position = new Position(customer.Latitude, customer.Longitude),
                    Label = customer.Name,
                    Address = customer.Address
                };

                MyMap.Pins.Add(pin);
     }
}

private void PositionMap()
{
     MyMap.MoveToRegion(
          MapSpan.FromCenterAndRadius(
               new Position(GlobalSetting.UserLatitude, GlobalSetting.UserLongitude),
               Distance.FromMiles(1)));
}

Vamos a aprovechar toda la versatilidad y potencia que nos brindan los Behaviors en Xamarin.Forms.

El concepto de Behavior es algo muy sencillo. Un Behavior espera por “algo” para hacer “algo”. Concretamos más. Un Behavior espera por “algo”. Puede ser un evento que se lanza, el cambio de una propiedad o cualquier otra acción personalizada que deseamos monitorear. Una vez que ese “algo” se desencadena, el Behavior puede hacer acciones muy variadas, desde cambiar el valor de una propiedad, lanzar un evento, hacer verificaciones o validaciones, etc.

Los Behaviors nos permiten encapsular lógica que se puede adjuntar a un componente específico. Generalmente ayudan a personalizar o completar ciertos componentes e incluso en muchas ocasiones son un a ayuda fundamental para mantener una estructura idónea al implementar patrones como MVVM.

Comenzamos creando la clase MapBehavior que debe de heredar de BindableBehavior<Map>:

public class MapBehavior : BindableBehavior<Map>
{

}

Para permitir tener acceso a la colección de pushpins vamos a crear una BindableProperty de tipo IEnumerable<Customer>:

public static readonly BindableProperty ItemsSourceProperty =
     BindableProperty.CreateAttached("ItemsSource", typeof(IEnumerable<Customer>), typeof(MapBehavior), 
          default(IEnumerable<Customer>), BindingMode.Default, null, OnItemsSourceChanged);

public IEnumerable<Customer> ItemsSource
{
     get { return (IEnumerable<Customer>)GetValue(ItemsSourceProperty); }
     set { SetValue(ItemsSourceProperty, value); }
}

Al recibir la información, añadiremos los pushpins al mapa y centraremos la posición deseada:

private static void OnItemsSourceChanged(BindableObject view, object oldValue, object newValue)
{
     var mapBehavior = view as MapBehavior;

     if (mapBehavior != null)
     {
          mapBehavior.AddPins();
          mapBehavior.PositionMap();
     }
}

Sencillo, ¿cierto?. Pues ahora llega el momento de utilizar el Behavior. Añadimos en la página el namespace XAML necesario:

xmlns:behaviors="clr-namespace:MyTaxiCompany01.Behaviors;assembly=MyTaxiCompany01"

Utilizamos el Behavior:

<AbsoluteLayout>
    <maps:Map
      AbsoluteLayout.LayoutFlags="All"
      AbsoluteLayout.LayoutBounds="0, 0, 1.0, 1.0">
      <maps:Map.Behaviors>
        <behaviors:MapBehavior 
             ItemsSource="{Binding Customers}" />
      </maps:Map.Behaviors>
    </maps:Map>
</AbsoluteLayout>

El resultado:

La aplicación de ejemplo

La aplicación de ejemplo

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

Ver GitHub

Hasta este punto hemos aprendido como utilizar mapas en Xamarin.Forms de forma básica. Sin embargo, en las aplicaciones que hacen un uso intensivo de mapas vemos características como:

  • Pushpins totalmente personalizados.
  • Pushpins dinámicos (se añaden, se quitan e incluso se desplazan).
  • Mostrar un  diálogo al pulsar un puhspin.
  • Traza de rutas.
  • Dibujo de figuras poligonales.

¿Cómo hacemos estas opciones en Xamarin.Forms?. En próximos artículos iremos profundizando en el uso de mapas viendo como realizar cada uno de los puntos anteriores.

Recuerda, cualquier tipo de duda o sugerencia es bienvenida en los comentario del artículo.

Más información

[Xamarin.Forms] Probando UI Sleutch

uisleuthIntroducción

Xamarin.Forms es un toolkit que crea una abstracción sobre la interfaz de usuario de Android, iOS y Windows Phone permitiendo desarrollarla una única vez con código C# o Extensible Application Markup Language (XAML). Actualmente tenemos disponibl Xamarin.Forms Previewer o lo que es lo mismo, una herramienta que nos permite visualizar en tiempo real cualquier cambio relacionado con el código XAML que define la UI. Sin embargo, existen grandes opciones que vienen de parte de la comunidad y que vienen a extender y ayudar a la experiencia disponible directamente en Visual Studio. De esta forma tenemos propuestas como Gorilla Player o como la herramienta que va a cubrir toda la atención de este artículo, UI Seuth.

UI Sleuth

UI Sleuth es una herramienta creada por Michael Davis actualmente disponible en fase Beta para Windows (próximamente disponible también para MacOS) que nos permite depurar nuestras aplicaciones Xamarin.Forms. Entre las principales características permite:

  • Conectar y manejar un dispositivo.
  • Ver el árbol de elementos que componen la UI.
  • Hacer prototipos de UI de forma rápida y sencilla.
  • Detectar errores de UI.

Podemos resumir las características en un inspector visual (UI) en tiempo real de aplicaciones Xamarin.Forms.

¿Y en comparación con otras herramientas?

Xamarin Previewer permite ver directamente la renderización de una página XAML en Visual Studio. La aplicación no corre en un emulador o dispositivo, es una aproximación visible directamente en el IDE.

Por otro lado, tenemos a Gorilla Player. Esta gran herramienta permite ver los cambios en el codigo XAML de una página en tiempo real en N emuladores o dispositivos. La aplicación no se encuentra en ejecución.

La instalación

Empezamos por el principio, realizar la instalación de la herramienta. Debemos accerder a la página de UI Sleuth, rellenar el formulario básico con nombre y correo (recuerda, se encuentra en fase beta, la clave actualmente es probar y reportar feedback!).

Página de la herramienta

Página de la herramienta

Tras rellenar el formulario, accedemos a la página de descarga.

Descargar la herramienta

Descargar la herramienta

Para instalar basta con hacer doble clic sobre el archivo descargado. La instalación es un proceso rápido y sencillo.

Instalando

Instalando

Los requisitos de la herramienta son:

  • Microsoft Windows 7+ 64bit
    Visual Studio 2012+
    Xamarin.Forms 2.0+
    Emulador Android 4.03+ o dispositivo
    Android SDK (opcional)

Preparar la solución para utilizar UI Sleuth

Tras instalar la herramienta debemos de preparar nuestra aplicación para poder ver cambios al vuelo. En el proyecto Android, debemos hacer clic secundario en Administrar paquetes NuGet…

Buscamos por “UISleuth.Android”:

Añadir paquete NuGet

Instalamos el paquete. A continuación, en la actividad principal, MainActivity.cs añadimos el siguiente código tras la llamada a LoadApplication:

#if DEBUG
UISleuth.Inspector.Init();
#endif

Todo listo!. Lanzamos la aplicación en un emulador o dispositivo real.

Conectando

Continuamos arrancando la herramienta UISleuth. Nos aparecerá un listado de emuladores o dispositivos conectados. Podemos conectar directamente pulsando el botón Connect.

Conectando

También podemos realizar un proceso de conexión manual utilizando la dirección IP del dispositivo.

Tras conectar, veremos la pantalla principal de la herramienta:

UISleuth

Tenemos:

  • Visual Outline: Este panel situado a la izquierda nos permite explorar el árbol visual que compone la interfaz de usuario.
  • History: Sencillo panel que guarda cada paso de cada movimiento realizado en la herramienta. También situado a la izquierda.
  • Properties (Attached Properties y Events): Panel muy importante y completo. Tenemos la posibilidad de gestionar de forma visual las propiedades y eventos de cada control que compone la UI.

Utilizando UI Sleuth

Vamos a utilizar la herramienta para crear una sencilla vista de Login. Desde la propia herramienta podemos añadir los elementos visuales que necesitamos. Vamos a utilizar:

  • StackLayout
  • Label
  • Entry
  • Button

Añadir nuevos elementos

Tras añadir los elementos, tenemos la posibilidad de editar todas sus propiedades:

Gestión de propiedades

A la hora de añadir diferentes elementos de la UI, tenemos la posibilidad de modificar, arrastrar y soltar dentro del árbol visual para modificar el Layout de la aplicación:

Reordenar elementos de la UI

E incluso, podemos probar la aplicación y ver una previsualización en la misma herramienta:

Probando la App!

En resumen

Seguimos esperando un editor visual que permite la construcción de interfaces de usuario de forma sencilla, arrastrando y soltando, etc. Sin embargo, cada vez tenemos más opciones disponibles para la edición y gestión de la UI de nuestras aplicaciones Xamarin.Forms. UI Sleuth permite ver cambios de una aplicación en ejecución, además de poder acceder a listado de controles para añadir, poder ver el árbol visual pudiendo hacer drag & drop en el mismo, etc. En breve llegarán más características (versión MacOS, soporte a listados, etc.). Sin duda, una opción más que interesante la de Michael Davis que seguro a muchos os gustará y que seguirá mejorando en próximos meses.

¿Y a ti que te parece la herramienta?

Más información