[Material] Xamarin Dev Day Madrid

El evento

El pasado sábado 26 de Noviembre, tenía lugar en Madrid el Xamarin Dev Days. Una jornada con varias sesiones técnicas, taller, regalos y mucho networking.

El resultado fue un fantástico día de desarrollo Xamarin con muchas preguntas, ayuda y tiempo para charlar entre todos rodeados de un café o unas pizzas.

El material

Pude participar en el evento con una de las sesiones. Nos centramos en el desarrollo de aplicaciones móviles multiplataforma utilizando Xamarin.Forms:

Comenzamos por una introducción de conceptos básicos, primera demo aplicando MVVM y terminamos repasando todas las últimas novedades como DataPages, Native Views o el desarrollo para Tizen.

Tras las sesiones, realizamos un muy divertido taller donde paso a paso, desarrollamos una aplicación Xamarin.Forms aplicando MVVM y accediendo a información meteorológica.

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

Ver GitHub

Quisiera terminar añadiendo algunos agradecimientos. Comienzo por los chicos de Liferay por las instalaciones y toda la ayuda; a Plain Concepts y Bravent por su patrocinio; a Xamarin también por patrocinar el evento; a mis compañeros Dachi Gogotchuri, Sergio Gasca, Ramón Esteban y Alejandro Campos por sus demos y ayudar con todo y por supuesto a los asistentes. Gracias a todos.

Más información

[Material Codemotion 2016] Introducción al desarrollo de HoloLens

El evento

El pasado 18 y 19 de Noviembre, en la universidad San Pablo CEU, tenía lugar el Codemotion 2016. Evento destinado a desarrolladores en España con más de 2000 desarrolladores, más de 30 comunidades técnicas y más de 150 sesiones técnicas.

El material

He tenido la oportunidad de participar este año hablando de desarrollopara HoloLens.

Desarrollo para HoloLens
Desarrollo para HoloLens

Tras una breve introducción donde repasamos conceptos como realidad virtual, realidad aumentada o que es un holograma, entramos de lleno a conocer las HoloLens. Conbinando presentaciones, el dispositivo físico y el portal del dispositivo conocimos las características, sensores y posibilidades.

A continuación, entramos de lleno a hacer una App. Utilizando Wave Engine realizamos una aplicación sobre el sistema solar (en directo).

Terminamos con algunas aplicaciones desarrolladas ya publicadas en la Store, consejos, preguntas y alguna sorpresa.

La presentación (versión reducida suprimiendo videos):

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

Ver GitHub

Más información

[Podcast Interfaz] Conociendo Xamarin

interfaz-podcastIntroducción

Recientemente, Rodrigo Díaz Concha, Windows Development MVP y Microsoft Regional Director en Mexico, ha lanzado un podcast (muy recomendado) llamado Interfaz. El objetivo del podcast es ser un medio de comunicación que toque diversos temas del espectro de tecnologías de software que tenemos a nuestro alcance hoy en día con una frecuencia semanal.

El podcast, conociendo Xamarin

En el episodio 9 del podcast, tengo el placer de poder participar hablado de Xamarin. Durante el episodio hablamos acerca de qué es Xamarin, las opciones para el desarrollo con Xamarin, las ventajas de usar Xamarin.Forms, el futuro de Xamarin y los errores comunes que las personas cometen al iniciar con esta tecnología.

¿Te resulta interesante?

Puedes escuchar el podcast a continuación.

Más información

[Xamarin.Forms] Un vistazo al uso de Native Views desde XAML

XamarinIntroducción

Xamarin.Forms añade una capa de abstracción sobre la capa de la interfaz de usuario que permite definir la misma una única vez para todas las plataformas con código C# o XAML. A pesar de la abstracción, podemos acceder a características específicas de la plataforma utilizando DependencyService o crear nuevos controles accediendo a características nativas gracias al uso de Custom Renders, efectos o Native Embbeding.

En el uso de Custom Renders o efectos, necesitamos crear una clase en la PCL con la definición del control o efecto y una clase en cada plataforma soportada con la implementación.

¿Y si se puede hacer todo de una forma más directa?

Native Views

Con Xamarin.Forms 2.3.3.+se introduce el concepto de Native Views. Se pueden incrustar directamente vistas nativas en el XAML de nuestra interfaz compartida ya sea utilizando proyectos compartidos o librerías portables.

Uso en Android

Añadir vistas nativas es realmente sencillo. Necesitamos declarar los namespaces XML (xmlns) necesarios:

xmlns:android="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
xmlns:androidForms="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.Platform.Android;targetPlatform=Android"

Tras añadir los namespaces correspondientes, podemos acceder directamente a controles nativos:

<android:CalendarView         
     x:Arguments="{x:Static androidForms:Forms.Context}" />

Podemos acceder directamente a las propiedades del control nativo como atributos XML. En caso de requerir el uso de argumentos podemos establecerlo utilizando x:Arguments.

En Android es necesario pasar el contexto de Xamarin.Forms. En caso contrario obtendremos un error:

System.MissingMethodException: Default constructor not found for type Android.Widget.xxxxx

El resultado:

Calendario nativo de Android
Calendario nativo de Android

El turno de iOS

En el resto de plataformas, es practicamente igual el uso de Native Views. Comenzamos definiendo el namespace necesario:

xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"

Y podemos acceder directamente a controles nativos:

<ios:UIDatePicker />

El resultado:

UIDatePicker
UIDatePicker

Y ahora Windows

En el caso de Windows, igualmente necesitamos declarar el namespace:

xmlns:uwp="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"

Y tenemos acceso a vistas nativas:

<uwp:CalendarDatePicker />

El resultado:

nativeviews-windows
CalendarDatePicker

Utilizando Native Views

Tras definir tres vistas, cada una con vistas nativas de cada plataforma, para utilizarlas en una página debemos definir el namespace correspondiente:

xmlns:nativeViews="clr-namespace:NativeViews.Views.Native"

Y añadir cada vista:

<Grid>
     <nativeViews:AndroidView />
     <nativeViews:IosView />
     <nativeViews:WindowsView />
</Grid>

Sencillo, ¿cierto?.

¿Qué ocurre al ejecutar la aplicación y cargar esta vista en Android (por ejemplo)?.

Sólo se renderizarán los elementos Xamarin.Forms y la vista nativa de Android. No se mostrará nada relacionada con las visats nativas de iOS o Windows. Igual comportamiento obtendremos en otras plataformas.

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.

Atener en cuenta

A la hora de utilizar Native Views en nuestros desarrollos hay que tener en cuenta que:

  • No se puede utilizar Native Views en una vista con XAMLC (compilación de XAML) activado.
  • No podemos utilizar x:Name en controles nativos.

one-more-thingOne more thing

La posibilidad de añadir directamente vistas nativas en el XAML de nuestras vistas compartidas en Xamarin.Forms es una nueva característica interesante pero en la mayoría de ocasiones nos interesará gestionar de una forma adecuada la interacción con los controles.

Native Views permite el uso de enlace a datos tanto en modo OneWay como TwoWay. Gracias a esta posibilidad podemos crear vistas realmente complejas de una forma más simple. En próximos artículos continuaremos profundizando en el concepto de Native Views centrándonos en el uso de enlace a datos. Permanece atento!

Más información

[Xamarin.Forms] Behavior para hacer scroll infinito

stack-04-wfIntroducción

Actualmente el control de tipo listado incluido en Xamarin.Forms incluye soporte a características avanzadas interesantes como el uso de plantillas diferentes para cada elemento del listado o la posibilidad de realizar Pull To Refresh.

A pesar de que el refresco de listados realizando Pull To Refresh es una forma bastante habitual y extendida, no es la única. También en ocasiones es necesario refrescar listados a la medida que se va realizando scroll, lo que se conoce como scroll infinito.

¿Cómo realizamos scroll infinito en Xamarin.Forms?

El evento ItemAppearing

El control ListView lanza el evento ItemAppearing cada vez que un elemento pasa a ser visible. Nuestra tarea para detectar por lo tanto si hemos llegado al final es que el último elemento visible es el último elemento disponible.

NOTA: Habitualmente siempre que sea posible se recomienda el uso de idntificadores para realizar las comprobaciones necesarias.

Creando un Behavior

Los Behaviors (o comportamientos en Español) nos permiten añadir lógica directamente en XAML para realizar acciones sin necesidad de escribir código extra en el code behind.

Vamos a crear un Behavior que asociado a un listado permita lanzar un comando llegado al final del scroll para solicitar nuevos elementos.

Comenzamos creando una clase que herede de Behavior<T>:

public class IniniteListScrollingBehavior : Behavior<ListView>
{

}

Debemos implementar:

  • Propiedad AssociatedObject: Control al que se adjuntará el Behavior, es decir, el ListView.
  • Método OnAttachedTo: Lanzado inmediatamente tras adjuntar el Behavior al control. Se recibe una referencia al control adjuntado idóneo para acceder a propiedades o eventos del mismo.
  • Método OnDetachingFrom: Lanzado cuando el Behavior se elimina del control. Lugar perfecto para realizar tareas de limpieza (gestión de suscripciones de eventos, liberar recursos, etc.).
public ListView AssociatedObject { get; private set; }

protected override void OnAttachedTo(ListView bindable)
{
     base.OnAttachedTo(bindable);

     AssociatedObject = bindable;
     bindable.BindingContextChanged += OnBindingContextChanged;
     bindable.ItemAppearing += OnItemAppearing;
}

protected override void OnDetachingFrom(ListView bindable)
{
     base.OnDetachingFrom(bindable);

     bindable.BindingContextChanged -= OnBindingContextChanged;
     bindable.ItemAppearing -= OnItemAppearing;
     AssociatedObject = null;
}

private void OnBindingContextChanged(object sender, System.EventArgs e)
{
     base.OnBindingContextChanged();
     BindingContext = AssociatedObject.BindingContext;
}

private void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
{
     var listview = ((ListView)sender);

     if (listview.IsRefreshing)
          return;
}

Vamos a utilizar el método ItemAppearing del ListView para lanzar un comando encargado de refrescar el listado. Necesitamos crear una BindableProperty de tipo ICommand en el Behavior:

public static readonly BindableProperty CommandProperty =
     BindableProperty.Create("Command", typeof(ICommand), typeof(IniniteListScrollingBehavior), null);

public ICommand Command
{
     get { return (ICommand)GetValue(CommandProperty); }
     set { SetValue(CommandProperty, value); }
}

En el método ItemAppearing del control:

private void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
{
     var listview = ((ListView)sender);

     if (listview.IsRefreshing)
          return;

     if (Command == null)
     {
          return;
     }

     if (Command.CanExecute(e.Item))
     {
          Command.Execute(e.Item);
     }
}

Accedemos al comando (siempre y cuando el listado no siga refrescando) y lo ejecutamos pasándole el último elemento visible como parámetro. Este parámetro lo utilizaremos desde la ViewModel para determinar si ese elemento es el último de la lista o no.

Utilizando el Behavior

Tras crear el Behavior ha llegado el momento de utilizarlo. Pero antes de lanzarnos de pleno…¿de dónde obtenemos la información?.

En la ViewModel tendremos una propiedad pública con el listado a mostrar:

private ObservableCollection<Monkey> _monkeys;

public ObservableCollection<Monkey> Monkeys
{
     get { return _monkeys; }
     set
     {
          _monkeys = value;
          RaisePropertyChanged();
     }
}

Utilizaremos también un par de propiedades para determinar:

  • IsBusy: Esta propiedad nos indicará cuando se esta realizando la carga de más información. Utilizada en la UI para mostrar un indicador visual de carga en caso necesario.
  • CurrentPage: Un entero que almacena el número de página utilizado al cargar información. Gran cantidad de APIs soportan paginación. En la mayoría de ocasiones necesitamos indicar el número de página a cargar (justo esta propiedad) y el número de elementos por página.
public bool IsBusy { get; set; }

public int CurrentPage { get; set; }

En nuestro ejemplo, para simplificar todo en la medida de lo posible y centrarnos en el uso del Behavior, vamos a cargar datos locales:

private void LoadItems(int pageSize = 10)
{
     IsBusy = true;

     if(Monkeys == null)
     {
          Monkeys = new ObservableCollection<Monkey>();
     }

     for (int i = CurrentPage; i < CurrentPage + pageSize; i++)
     {
          Monkeys.Add(new Monkey()
          {
               MonkeyId = i + 1,
               Name = string.Format("Monkey {0}", i + 1)
          });
     }

     CurrentPage = Monkeys.Count;
     IsBusy = false;
}

El Behavior utilizará un comando para refrescar la información:

private ICommand _refreshCommand;

public ICommand RefreshCommand
{
     get { return _refreshCommand = _refreshCommand ?? new DelegateCommand<Monkey>(RefreshCommandExecute, RefreshCommandCanExecute); }
}

public bool RefreshCommandCanExecute(Monkey monkey)
{
     return !IsBusy && 
            Monkeys.Count != 0 && 
            Monkeys.Last().MonkeyId == monkey.MonkeyId;
}

public void RefreshCommandExecute(Monkey monkey)
{
     LoadItems();
}

Para utilizarlo en nuestra UI compartida XAML, debemos crear un namespace:

xmlns:behavior="clr-namespace:InfiniteScrollingBehavior.Behaviors;assembly=InfiniteScrollingBehavior"

Utilizando la propiedad Behaviors del listado, adjuntamos el Behavior creado enlazando con el comando previamente visto.

<ListView
     ItemsSource="{Binding Monkeys}"
     IsRefreshing="{Binding IsBusy}"
     HasUnevenRows="true">
     <ListView.ItemTemplate>
          <DataTemplate>
               <ViewCell>
                    <templates:MonkeyTemplate />
               </ViewCell>
           </DataTemplate>
       </ListView.ItemTemplate>
       <ListView.Behaviors>          
          <behavior:IniniteListScrollingBehavior  
                Command="{Binding RefreshCommand}">
          </behavior:IniniteListScrollingBehavior>
     </ListView.Behaviors>
</ListView>

El resultado:

inifinitescrollingbehavior

Sencillo y además facilmente reutilizable.

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

[Podcast] Xamarin: Mitos y verdades

mic-02El podcast

Recientemente los compañeros Camilo Galiana y Rodrigo Díaz crearon un podcast llamado Just In Time. Un podcast sobre desarrollo movil, buenas practicas, lenguajes y desvarios varios.

En el primer captítulo, he tenido el placer de participar junto a Josué Yeray y Marcos Cobeña para hablar de Xamarin. El enfoque buscado era tratar aspectos importantes relacionados con el desarrollo y uso de Xamarin desde un punto de vista neutro y desde la experiencia. En el podcast tratamos aspectos como:

  • El rendimiento en comparación con aplicaciones nativas.
  • Cantidad de código compartido en aplicaciones “reales”.
  • Herramientas de Xamarin e integración de Visual Studio en comparación con las herramientas nativas.
  • Uso de plugins y de librerías nativas, ventajas y dificultades.
  • Frecuencia y estabilidad de cada nueva versión.
  • Etc.

Si te resulta interesante, puedes escuchar el podcast en el siguiente enlace.

Más información