[Material] dotNetMálaga 2019: Crear interfaces de usuario atractivas con Xamarin.Forms

El evento

El pasado 28 de Septiembre tenía lugar la dotNetMálaga 2019. Un gran día repleto de sesiones técnicas de tecnologías .NET, desde Xamarin, IA, Docker, etc.

dotNetMálaga 2019

Quisiera agradecer a todos los ponentes y asistentes por hacer posible el evento. Y por supuesto, mi enhorabuena a toda la organización por hacer que todo fluyese de forma tan natural.

El material

He tenido en placer de poder participar en el evento con una sesión acerca de Xamarin.Forms y formas de crear interfaces de usuario atractivas.

Crear interfaces atractivas visualmente con Xamarin.Forms

A continuación, la presentación utilizada:

En esta sesión vimos:

  • El uso de diccionario de recursos y temas.
  • Animaciones.
  • Transiciones.
  • Uso de SkiaSharp.
  • Lottie.
  • Visual.
  • Gradientes.
  • Nuevos controles (CollectionView, RefreshView).

Puedes encontrar todos los ejemplos en GitHub:

Ver GitHub

Hasta el año próximo!

Más información

Anuncios

[Xamarin.Forms] Ahora podemos usar contenido Html en Labels

Introducción

Uno de los controles habituales en cualquier aplicación Xamarin.Forms es el control Label. Al fin y al cabo, necesitamos mostrar texto de diversas formas. Es por eso, que es uno de los controles que recibe mejoras de forma constante. Recientemente hemos recibido espaciado entre carácteres, padding y soporte a contenido HTML.

Html como contenido

Antes que nada, HTML es potente y permite una cantidad de contenido diverso. No, no vas a poder añadir un video de YouTube como contenido. Se soportan etiquetas básicas como negritas, cabeceras, etc.

¿Cómo utilizar HTML como contenido?

Se ha añadido la propiedad TextType al Label. Con esta propiedad podemos indicar si queremos renderizar el texto directamente, Text, o como HTML.

Label htmlLabel = new Label() { TextType = TextType.Html };

De modo que, para establecer el contenido seguimos utilizando la propiedad Text:

htmlLabel.Text = "<h1>Hello World!</h1><br/>SecondLine";

Desde XAML, para utilizar HTML como contenido tenemos dos opciones:

  • Codificar la cadena HTML.
  • Usar CDATA.

Codificar la cadena, aunque es una opción, requiere trabajo extra:

<Label TextType="Html">
    <Label.Text>
        &lt;h1&gt;Hello World!&lt;/h1&gt;&lt;br/&gt;SecondLine
    </Label.Text>
</Label>

Usando CDATA:

<Label TextType="Html">
     <Label.Text>
          <x:String>
          <![CDATA[
          <h1>Hello world!</h1><br/>SecondLine
          ]]>
          </x:String>
     </Label.Text>
</Label>

El resultado:

Label con contenido HTML

¿Qué te parece esta nueva opción?. Recuerda, puedes dejar cualquier feedback o comentario en la entrada!.

Más información

[Xamarin.Forms] Un vistazo a RefreshView

Introducción

A día de hoy, estamos a acostumbrados (y cada vez más) a utilizar gestos para realizar acciones concretas en las aplicaciones móviles. Actualizar el contenido, cambiar de sección, etc. El objetivo final es diverso pero sin duda alguna, una de las acciones con gestos más utilizadas es el Pull To Refresh.

Pull to Refresh

Pull To Refresh

En diseño para dispositivos móviles, este efecto es el gesto que se realiza para la actualización de contenidos. Es decir, el pull to refresh es el gesto que se hace deslizando (normalmente) la parte superior hacia abajo para actualizar los contenidos.

Usando RefreshView

RefreshView llega como un nuevo control en Xamarin.Forms que permite hacer pull to refresh sobre cualquier contenido scrollable (ScrollView, ListView, CollectionView, etc.). El uso es muy sencillo:

<RefreshView>
     <ScrollView>
     </ScrollView>
</RefreshView>

Ya tendríamos lo suficiente para poder hacer pull to refresh sobre el contenido del ScrollView. En este artículo, voy a utilizar una aplicación antigua del tiempo que he actualizado para usar RefreshView además de CollectionView.

El comportamiento y apariencia de RefreshView se establece con algunas propiedades básicas:

  • BackgroundColor: Color de fondo del control.
  • RefreshColor: Color del indicador de carga.
  • IsRefreshing: Propiedad de tipo bool que indica si se esta refrescando el contenido o no. Si se establece a True se desencadena un refresco.
  • Command: Por supuesto, tenemos un comando para ejecutar la lógica de refresco en el contexto (ViewModel). Además de la propiedad Command contamos con CommandParameter.

De modo que nuestro RefreshView quedaría:

<RefreshView
     BackgroundColor="{StaticResource WhiteColor}"
     RefreshColor="{StaticResource AccentColor}"
     IsRefreshing="{Binding IsBusy}"
     Command="{Binding ReloadCommand}">
     <ScrollView>
     ...
     </ScrollView>
</RefreshView>

El resultado:

 

Usando RefreshView

Puedes encontrar el código del ejemplo en GitHub:

Ver GitHub

One more thing

En UWP contamos con un Platform Specific que permite especificar la orientación del pull to refresh:

refreshView.On<Windows>().SetRefreshPullDirection(RefreshPullDirection.BottomToTop);

Permite:

  • Desde arriba.
  • Desde abajo.
  • Desde la izquierda.
  • Desde la derecha.

¿Qué te parece RefreshView?. Recuerda, cualquier comentario es bienvenido!.

Más información

[Xamarin.Forms] RelativeSource Binding

Introducción

Estas usando un control enlazado a una colección (por ejemplo, un listado de peliculas) y en cada elemento cuentas con un botón para añadir la pelicula a favoritos. Por defecto, cada elemento tendra como contexto la pelicula de la colección enlazada al listado y añadir un comando en cada elemento no suena como la mejor idea pero…¿que hacemos en este caso?.

RelativeSource

Contábamos ya con otras soluciones para hacer Binding a un elemento visual (x:Reference) pero nos llega RelativeSource, la solución ideal en casos como el anterior.

RelativeSource es una extensión de marcado que se utiliza en casos de enlace particulares cuando intentamos vincular una propiedad de un objeto a otro de sus padres relativos. 

Veamoslo con un ejemplo sencillo. Vamos a trabajar con tareas:

public class TodoItem
{
     public string Name { get; set; }
     public string Description { get; set; }
     public bool IsDone { get; set; }
}

De modo que en la ViewModel contaremos con un listado de tareas:

Items = new ObservableCollection<TodoItem>
{
     new TodoItem
     {
          Name = "Create RelativeSource Demo"
     },
     new TodoItem
     {
          Name = "Buy Milk"
     },
     new TodoItem
     {
          Name = "Go for a walk"
     }
};

Y un comando:

public ICommand DeleteTodoItemCommand => new Command<TodoItem>(DeleteTodoItem);

NOTA: Fíjate que cada TodoItem no cuenta con un comando.

En la interfaz de usuario:

<ListView 
     ItemsSource="{Binding Items}">
     <ListView.ItemTemplate>
          <DataTemplate>
               <ViewCell>
                    <Grid>
                         <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="*" />
                              <ColumnDefinition Width="80" />
                         </Grid.ColumnDefinitions>
                         <Label 
                              Grid.Column="0"
                              Text="{Binding Name}"/>
                         <Button 
                              Grid.Column="1"
                              Text="Delete" 
                              CommandParameter="{Binding}" 
                              Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MainViewModel}}, Path=DeleteTodoItemCommand}"/>
                    </Grid>
               </ViewCell>
          </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

El resultado:

Usando RelativeSource

El comando hace uso de RelativeSource para acceder al ancestro de tipo MainViewModel y Path, el comando.

Puedes encontrar el código del ejemplo en GitHub:

Ver GitHubOtra extensión de marcada añadida que viene a solucionar ciertos casos. ¿Qué te parece el añadido?.

Recuerda, cualquier comentario o feedback es bienvenido en los comentarios de la entrada.

Más información

[Evento] Monkey Conf 2019

El evento

Y vuelve el evento técnico Xamarin que estabas esperando, Monkey Conf 2019!.

Monkey Conf 2019

Tras el éxito del evento del año pasado, regresamos con una nueva edición de la Monkey Conf. Volverá a ser un evento gratuito, en el que trataremos temas relacionados con desarrollo móvil, Xamarin, Xamarin.Forms, App Center, testing y más…

La fecha

Será el próximo Sábado, 30 de Noviembre de 09:30h a 18:30h (GMT+1). Tendremos dos tracks en paralelo con diferentes sesiones técnicas de 50 minutos de duración cada una. Además contaremos con regalos y sorpresas!.

¿Te apuntas?

NOTA: Las entradas del evento son gratuitas pero limitadas!

El lugar

El evento se celebrará en Liferay. Dirección detallada:

Paseo de la Castellana, 280, 28046 Madrid, Madrid

Oficinas de Liferay

Call 4 Papers

¿Has desarrollado una aplicación con Xamarin?, ¿quieres hablar acerca de como usas App Center?, ¿revisar las próximas novedades de Xamarin.Forms?, ¿un taller o mesa redonda?. El C4P del evento está abierto y estoy seguro que puedes hablar sobre algun tema que interese y ayude al resto!.

Más información

[Xamarin October Challenge] Best Practices

Introducción

Los retos (Challenges) han sido una de las gratas sorpresas en la comunidad de Xamarin en este año. No solo hemos tenido varios retos, además han sido recibidos y apoyados de una forma muy positiva.

¿Por qué no tener otro reto en el mes de Octubre?.

Nuevo Challenge

De esta forma nos llega de la mano de Claudio Sanchez el reto de Octubre basado en buenas prácticas. Hablamos de buenas prácticas en todos los ámbitos del desarrollo Xamarin: estructura del proyecto, DevOps, Testing, creación de APIs, etc.

¿Cómo funciona?

Como otros retos anteriores, la idea es llegar a contar con un artículo por cada día del mes. En esta ocasión todo esta centralizado en un repositorio en GitHub. En el repo puedes ver dos aspectos fundamentales:

  • Calendario de fechas: Donde ver cuales están libres y poder elegir cual prefieres ocupar.
  • Tabla de contenido: Un listado con temas y posibles ideas que puedes abordar.

¿Cómo participo?

Debes reservar un hueco!. Para hacerlo bastará con crear una issue en el repositorio:

Reservar hueco

Tras reservar el hueco, podrás escribir el artículo en un archivo de markdown y enviar una Pull Request al repositorio del reto. Por supuesto, también podrás publicar el artículo en tu blog.

Al final del reto, habrá un evento donde se repasarán todas las contribuciones, etc.

Suena divertido, ¿te animas a participar?.

NOTA: El artículo debe ser en ingles.

Más información

Xampane, nuevos Layouts para Xamarin.Forms

Layouts en Xamarin.Forms

A la hora de organizar y posicionar los elementos visuales que componen la interfaz de usuario en Xamarin.Forms, hacemos uso de Layouts.

Layouts

Tenemos una enorme variedad de Layouts en Xamarin.Forms. Podemos posicionar de forma absoluta; de forma relativa; apilar elementos; etc. Con un uso correcto de los mismo se pueden cubrir la mayoría de necesidades pero…¿qué ocurre cuando no nos encaja al 100%?.

Por ejemplo, si necesitamos posicionar botones circulares alrededor de una imagen circular (perfil de usuario), ¿que Layout nos encaja?. Podemos conseguir nuestro objetivo con los Layouts disponibles pero probablemente con ajustes específicos para posicionar cada elemento. ¿Podemos conseguirlo de forma más sencilla?.

Creando Layouts

Un Layout es una clase que deriva de View. Podemos crear Layouts personalizados en Xamarin.Forms con clases que hereden de Layout<T>.

public class MyCustomayout : Layout<View>
{

}

Antes de continuar, vamos a repasar algunos conceptos básicos.

Cada VisualElement define un método Measure que se encarga de calcular el tamaño del elemento, y un método Layout que especifica el área rectangular donde se va a representar. Cuando se inicia una aplicación Xamarin.Forms y se muestra la primera página,  se lanza  un “ciclo de Layout” que consta de varias llamadas Measure primero y, a continuación, se lanza Layout.

Cada clase que derive de Layout o Layout<View> debe sobrecargar el método OnMeasure, que es donde el Layout determina el tamaño que debe tener realizando llamadas al método Measure de sus elementos hijos. Además, cada clase Xamarin.Forms que contenta Content o Children (como es el caso del Layout) cuenta con un método LayoutChildren que es donde se posicionan y ajustan los elementos hijos.

Ten en cuenta que, normalmente un cambio en el tamaño de un elemento afecta a cómo el Layout organiza a sus elementos secundarios. Por lo tanto, un cambio en el tamaño de un elemento iniciará un “ciclo de Layout” para el Layout y se llamarán a los métodos OnMeasure y LayoutChildren. A este proceso, se le llama invalidación. Por ejemplo, si un Label dentro del Layout pasa de tener fuente 12 a 24, si tamaño deja de ser correcto. El elemento pasaría a estar marcado como no válido y se ejecutaría el método InvalidateMeasure.

public class MyCustomLayout : Layout<View>
{
     protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
     {

     }
 
     protected override void LayoutChildren(double x, double y, double width, double height)
     {

     }
}

Xampane

Xampage es una librería que añade nuevos Layouts para Xamarin.Forms. Actualmente la librería cuenta con los siguientes Layouts:

  • CircularLayout
  • DockLayout
  • HexLayout
  • UniformGrid
  • WrapLayout

La librería esta disponible en NuGet. Para instalar la misma basta con añadir el paquete:

Install-Package XamPane -Version 1.0.0

CircularLayout

CircularLayout es un Layout que organiza a sus elementos hijos en una disposición circular. Tiene algunas propiedades útiles para permitir cierta personalización como la propiedad Orientation (en sentido horario o antihorario).

<xampane:CircularLayout
    Orientation="Clockwise">
    <BoxView Color="Black" CornerRadius="6" WidthRequest="6" HeightRequest="6" />       
    <BoxView Color="Red" CornerRadius="12" WidthRequest="12" HeightRequest="12" xampane:CircularLayout.Angle="0" xampane:CircularLayout.Radius="120" />
    <BoxView Color="Green" CornerRadius="12" WidthRequest="12" HeightRequest="12" xampane:CircularLayout.Angle="10" xampane:CircularLayout.Radius="120" />
    <BoxView Color="Blue" CornerRadius="12" WidthRequest="12" HeightRequest="12" xampane:CircularLayout.Angle="20" xampane:CircularLayout.Radius="120" />
    <BoxView Color="Yellow" CornerRadius="12" WidthRequest="12" HeightRequest="12" xampane:CircularLayout.Angle="30" xampane:CircularLayout.Radius="120" />
    <Label Text="1" xampane:CircularLayout.Angle="30" xampane:CircularLayout.Radius="90" />
    <Label Text="2" xampane:CircularLayout.Angle="60" xampane:CircularLayout.Radius="90" />
    <Label Text="3" xampane:CircularLayout.Angle="90" xampane:CircularLayout.Radius="90" />
    <Label Text="4" xampane:CircularLayout.Angle="120" xampane:CircularLayout.Radius="90" />
    <Label Text="5" xampane:CircularLayout.Angle="150" xampane:CircularLayout.Radius="90" />
    <Label Text="6" xampane:CircularLayout.Angle="180" xampane:CircularLayout.Radius="90" />
    <Label Text="7" xampane:CircularLayout.Angle="210" xampane:CircularLayout.Radius="90" />
    <Label Text="8" xampane:CircularLayout.Angle="240" xampane:CircularLayout.Radius="90" />
    <Label Text="9" xampane:CircularLayout.Angle="270" xampane:CircularLayout.Radius="90" />
    <Label Text="10" xampane:CircularLayout.Angle="300" xampane:CircularLayout.Radius="90" />
    <Label Text="11" xampane:CircularLayout.Angle="330" xampane:CircularLayout.Radius="90" />
    <Label Text="12" xampane:CircularLayout.Angle="360" xampane:CircularLayout.Radius="90" />
</xampane:CircularLayout>

El resultado:

CircularLayout

Las propiedades del Layout que nos permiten organizar los elementos son:

  • Orientation: Permite organizar los elementos en el sentido de las agujas del reloj (Clockwise) o en sentido contrario (CounterClockwise).
  • Ange: Valor numérico entre 0 y 360. Permite posicionar cualquier elemento en un angulo concreto del círculo.
  • Radius: La distancia con respecto el centro.

DockLayout

DockLayout permite acoplar los elementos hijos a la parte superior, inferior, izquierda o derecha. Por defecto, el último control, si no se le da una posición de acoplamiento específica, llenará el espacio restante. Se puede conseguir lo mismo con el Grid, pero para las situaciones más simples, DockLayout será más fácil de usar. 

<xampane:DockLayout
    LastChildFill="False">
    <Button xampane:DockLayout.Dock="Top" Text="Top" HeightRequest="50"/>
    <Button xampane:DockLayout.Dock="Bottom" Text="Bottom" HeightRequest="50"/>
    <Button xampane:DockLayout.Dock="Left" Text="Left" WidthRequest="60"/>
    <Button xampane:DockLayout.Dock="Left" Text="Left" WidthRequest="60"/>
    <Button xampane:DockLayout.Dock="Right" Text="Right" WidthRequest="80"/>
    <Button xampane:DockLayout.Dock="Right" Text="Right" WidthRequest="80"/>
</xampane:DockLayout>

El resultado:

DockLayout

Contamos con la propiedad adjunta Dock. Esta propiedad permite acoplar cualquier elemento hijo a la parte superior, inferior, izquierda o derecha. Por otro lado, la propiedad LastChildFill (bool) permite indicar si el último elemento hijo ocupa todo el espacio restante disponible o no.

HexLayout

Organiza los elementos siguiento un patrón de panel de abejas.

<xampane:HexLayout
    RowCount="3"
    ColumnCount="3"
    Orientation="Vertical">
    <polygon:PolygonFrame Grid.Row="0" Grid.Column="1" OffsetAngle="90" BackgroundColor="Red"/>
    <polygon:PolygonFrame Grid.Row="0" Grid.Column="2" OffsetAngle="90" BackgroundColor="Green"/>
    <polygon:PolygonFrame Grid.Row="1" Grid.Column="0" OffsetAngle="90" BackgroundColor="Blue"/>
    <polygon:PolygonFrame Grid.Row="1" Grid.Column="1" OffsetAngle="90" BackgroundColor="Yellow"/>
    <polygon:PolygonFrame Grid.Row="1" Grid.Column="2" OffsetAngle="90" BackgroundColor="Orange"/>
    <polygon:PolygonFrame Grid.Row="2" Grid.Column="1" OffsetAngle="90" BackgroundColor="Purple"/>
    <polygon:PolygonFrame Grid.Row="2" Grid.Column="2" OffsetAngle="90" BackgroundColor="Pink"/>
</xampane:HexLayout>

Veamos como organiza los elementos:

HexLayout

El panel permite definir la orientación con la propiedad Orientation (horizontal o vertical). Para organizar los elementos usamos las propiedades adjuntas Grid y Row.

UniformGrid

UniformGrid (es el Layout más simple incluido en la librería) es como un Grid, es decir, permite definir múltiples filas y columnas, pero con una diferencia importante: todas las filas y columnas tendrán el mismo tamaño.

<xampane:UniformGrid>
    <BoxView Color="Red" />
    <BoxView Color="Yellow" />
    <BoxView Color="Orange" />
    <BoxView Color="Purple" />
    <BoxView Color="Blue" />
    <BoxView Color="Green" />
    <BoxView Color="LightGreen" />
    <BoxView Color="Gray" />
    <BoxView Color="Pink" />
</xampane:UniformGrid>

UniformGrid

WrapLayout

El WrapLayout colocará cada uno de sus elementos hijos al lado del otro, horizontalmente (de forma predeterminada) o verticalmente, hasta que no haya más espacio, momento en el que pasara  la siguiente línea y continuará. 

<xampane:WrapLayout 
    Orientation="Vertical"
    Spacing="6"
    HorizontalOptions="Center">
    <BoxView Color="Red" />
    <BoxView Color="Yellow" />
    <BoxView Color="Orange" />
    <BoxView Color="Purple" />
    <BoxView Color="Blue" />
    <BoxView Color="Green" />
    <BoxView Color="LightGreen" />
    <BoxView Color="Gray" />
    <BoxView Color="Pink" />
</xampane:WrapLayout>

El resultado:

WrapLayout

La propiedad fundamental del control es Orientation con las opciones Vertical u Horizontal.

Puedes encontrar el código de la librería disponible en GitHub:

Ver GitHub

¿Qué te parece la librería?, ¿qué Layout te resulta más útil?. Recuerda, puedes dejar cualquier duda o comentario!.

Más información

¿Hablamos de Xamarin.Forms?

Introducción

Gracias a este blog, comunidades técnicas, eventos de comunidad y otras actividades, he tenido (tengo) la oportunidad de hacer networking con miembros de la comunidad Xamarin. El networking siempre es una experiencia fantástica para compartir conocimientos, aprender cosas nuevas, etc.

Ahora, formando parte del equipo de Xamarin.Forms, conozco de primera mano las ganas por parte del todo el equipo para continuar progresando y mejorando. Aunque siempre se dan vueltas a la duda, ¿qué se debe añadir en próximas versiones?, ¿que hace realmente falta?, ¿que debe mejorar?.

Office hours

Tengo la oportunidad de crear Office hours. ¿Qué es esto?. Sencillo, accediendo a este enlace, puedes reservar 30 minutos para que hablemos juntos acerca de Xamarin.Forms. Podemos hablar de diferentes temas, pero los principales serían:

  • Resolver dudas a la hora de colaborar en Xamarin.Forms. Si quieres colaborar de cualquier forma o bien, si conoces un bug de Xamarin.Forms y quieres saber como notificarlo.
  • Hablar de funcionalidad actual que quieres que se mejore. Por ejemplo, echas en falta una propiedad, evento específico.
  • Hablar de funcionalidad que te gustaría tener. Nuevo control, Layout, etc.
  • Etc.

Estas sesiones se tendran en cuenta para saber que interesa en próximas versiones, así como registrar/destacar bugs a corregir. En definitiva, ayudarán a continuar mejorando Xamarin.Forms.

¿Hablamos?

¿Cómo colaborar con Xamarin.Forms?

Contribuir en Xamarin.Forms

Una de los puntos a favor de Xamarin es su increíble comunidad. Una comunidad activa haciendo constantemente actividades (eventos online, eventos presenciales, etc.) y creando nuevo contenido (artículos, ejemplos, plugins, etc.). Con el paso del tiempo es fantástico ver más y más plugins además de diferentes retos de UI y otro tipo de contenidos que son de ayuda para todos.

Por otro lado, Xamarin.Forms es un proyecto Open Source. Esto tiene una serie de implicaciones entre las que podemos destacar:

  • El código esta disponible. Cualquiera puede revisarlo, compilarlo e incluso aplicar modificaciones.
  • Las issues y PRs son abiertas. De nuevo, cualquiera puede añadir una opinión en una PR o en una futura nueva funcionalidad.
  • Los proyectos de GitHub son públicos. Se puede ver en cada momento en que se esta trabajando, que esta pendiente, etc.
  • La Wiki con aspectos como el Roadmap es público.

Todos los factores anteriores han provocado que cada vez haya un número mayor de colaboraciones de miembros de la comunidad en el repositorio oficial de Xamarin.Forms.

Como miembro del equipo de Xamarin.Forms y habiendo sido colaborador previamente es algo que me encanta ver y fomentar. Por otro lado, recibo en ocasiones correos o mensajes en varios medios (Slack, Skype, etc.) preguntando como puede ayudar a corregir X issue o sencillamente como compilar Xamarin.Forms.

En este artículo, voy a hacer un repaso en las diferentes formas en las que se puede contribuir en Xamarin.Forms, así como compilar el proyecto, poder tomar issues o mejoras, etc.

¿Te interesa?. Vamos a por ello!.

Consejos antes de comenzar

Antes de empezar, colaborar en proyectos Open Source tiene partes positivas como:

  • Es una forma divertida de aprender.

Sin embargo, si nunca has colaborado antes probablemente tengas algunas dudas. La primera de ellas será como hacerlo. Para eso espero que este artículo sea de ayuda. El segundo de los posibles problemas esta en el conocido “síndrome del impostor”. Dudas si lo que haces es correcto,  etc. En este punto, no te preocupes!. Si hay algo que se pueda mejorar, lo verás en el feedback. Es parte de la “gracia” de colaborar así, aprenderás posiblemente cosas nuevas.

Tan solo recuerda:

  • No tengas dudas. Aprenderás cosas nuevas como yo y todos lo hacemos a diario.
  • Puedes preguntar al crear la PR lo que necesites!.

Formas de contribuir

Lo primero de todo, contribuir tiene varias definiciones aunque en este caso:

“se trata de ayudar y concurrir con otros al logro de un cierto fin”

Se puede ayudar de muchas formas!. No tienes porque implementar la espectacular funcionalidad X para poder contribuir.

Vamos a repasar las diferentes opciones disponibles:

  • Reportar una issue.
  • Aportar ideas para nueva funcionalidad.
  • Correcciones en la documentación.
  • Corregir una issue.
  • Nueva funcionalidad.

Reportar una issue

Es una de las formas más sencillas de contribuir. Tienes un problema usando Xamarin.Forms, algo que no se comporta como debería. Abre una issue. De esta forma, avisarás que algo no funciona como debe; se corregirá y en el futuro otros devs tendrán la corrección gracias a que avisaste el problema.

Los pasos a seguir son sencillos:

  1. Logra reproducir un problema de forma constante.
  2. Escribe una Issue explicando el problema. Lo fundamental es detallar en pasos como reproducir el problema.
  3. Detallada cual es el comportamiento que estas obteniendo y cual es el esperado (ayuda a determinar si es una Issue o no).
  4. Añade la versión de Xamarin.Forms utilizada así como la plataforma o plataformas afectadas.
  5. Si es posible, añade algunas capturas.
  6. Si es posible (ayuda muchísimo), añade un pequeño ejemplo adjunto donde reproducir el problema.

Voila!. Sencillo, ¿verdad?.

Recomiendo revisar las issues con el tag excellent-report para ver ejemplos de buenos reportes (buena descripción, pasos, ejemplo adjunto, etc.).

excellent-report

Aportar ideas, añadir nueva funcionalidad

“Estaría genial tener esta propiedad en este control”. Haz una propuesta. Es sencillo, al final es como escribir una issue pero con ligeros cambios.

Los pasos a seguir serían:

  1. Piensa, analiza y piensa de nuevo tu idea.
  2. Abre una issue con el título “[Enhancement] …” y añade una descripción detallada de lo que buscas con esta mejora.
  3. Si has pensado una posible definición para la API añadela.
  4. Si puedes, añade un pequeño ejemplo (Scenario) donde enseñar como se usaría la nueva funcionalidad.
  5. ¿Afecta a alguna API existente?. Indícalo.
  6. Si puedes, añade el nivel de dificultad necesario para implementar la nueva funcionalidad (bajo, medio, alto).
  7. Añade el tag enhancement.

Todo listo!. Puedes ver ejemplos de mejoras buscando en GitHub en las Issues por el tag enhancement. Veamos un ejemplo:

Mejoras

NOTA: Una vez enviada una propuesta, puedes seguir su estado. Revisa el siguiente enlace para conocer los posibles estados (aceptada, rechazada, en progreso, etc.).

Actualizar documentación

¿Encontraste algún error en la documentación?. Puedes enviar también correcciones en la documentación de la Wiki.

Corregir una issue

En este nivel de contribución se ha seleccionado una issue específica a corregir, cuentas con el código fuente sincronizado y ya te dispones a modificar código. Vamos a ver con más detalles este proceso un poco más adelante.

Añadir una nueva funcionalidad

Similar al caso anterior. La diferencia radica que en este caso creas una funcionalidad nueva en lugar de corregir una issue.

Compilar el proyecto

Para compilar el proyecto debemos comenzar por tener el mismo. Es sencillo:

git clone https://github.com/xamarin/Xamarin.Forms.git c:\XamarinForms

Si estas usando Visual Studio para Windows, tras obtener el proyecto no deberás hacer nada especial para compilarlo. Abre la solución Xamarin.Forms.sln y pulsa F5.

Aunque, la solución de Xamarin.Forms tiene varios tipos de proyectos con dependencias del SDK de UWP, .NET Core, etc. Si tienes errores al cargar este tipo de proyectos, primero hay que instalar algunas de las dependencias.

En caso de utilizar Visual Studio para macOS, para evitar problemas de compilación, mi compañero Shane Neuville ha creado un script.

#!/bin/bash

# If you are on Visual Studio for Mac 2017 Turn off automatic package restore before running this script
# If you are on Visual Studio for Mac 2019 you do not need to turn off automatic package restore
# Visual Studio => Preferences => Nuget => General => uncheck the Package Restore box
# Needing to turn restore off isn't necessary in the latest preview releases of VS Mac

# Clean
git clean -dxf

# NuGet restore
msbuild /t:restore Xamarin.forms.sln

# Build XF build tasks
msbuild Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj

# ensure resources are all in sync otherwise first run might cause a Resource ID not found error
msbuild Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj /t:rebuild

# open in vsmac and should be able to build/run from here
open Xamarin.Forms.sln

NOTA: Visual Studio para macOS soportará MultiTargeting lo que facilitará la compilación de la solución sin script pronto.

Si compilando sigues con problemas, recomiendo:

git clean -xdf

Conociendo el proyecto

La solución de Xamarin.Forms es relativamente grande así que, vamos a ver las claves para que puedas centrar el foco en lo importante.

La solución de Xamarin.Forms

Xamarin.Forms

Cuando se buscan las implementaciones de las abstracciones de controles, bindings , triggers y otro código que no sea específico de plataforma, estos proyectos son la clave.

Xamarin.Forms.Xaml

Extensiones de marcado y otros conceptos clave de XAML lo encontrarás en este proyecto.

Xamarin.Forms.Material

Aquí encontrarás lo necesario relacionado con Visual (de momento Material).

Xamarin.Forms.Maps

Por el nombre probablemente ya sepas que aquí encontrarás a logica del control de mapas.

Platforms

Estos proyectos contienen las implementaciones específicas de cada plataforma. Al agregar nuevos controles o corregir errores relacionados con los controles, aquí es donde efectuará esos cambios.

Control Gallery

Estos proyectos son en realidad una aplicación Xamarin.Forms a modo de galería que incluye todos los controles de Xamarin.Forms disponibles y, lo que es más importante, cuentan con una gran cantidad de UITests de errores previos. Cuando se trabaja en la corrección de un error, o simplemente para investigar cómo se espera que funcione un control, esta aplicación es lo que buscas!.

Xamarin.Forms Control Gallery

Trabajar en una corrección

Ya tienes el proyecto sincronizado y tienes una Issue seleccionada. Ahora si, manos a la obra. Pero antes de comenzar, crea una nueva rama partiendo de lo último disponible en master.

No se requiere cumplir un patrón específico a la hora de crear la rama. Mis recomendaciones serían:

  • Si es un fix, puedes crear una rama “fix{id}” donde el id es el identificador de la Issue.
  • Puedes usar un nombre descriptivo. Por ejemplo, si estas corrigiendo un error al seleccionar un elemento en el ListView podría ser algo como “fix_listview_selectitem”.
  • También puedes usar una combinación de las ideas anteriores. Por ejemplo: “fix_1234_listview_selectitem”.

A la hora de trabajar con el código recuerda cumplir las guías de estilo de código usadas en la .NET Foundation.

Una vez aplicados los cambios necesarios, considera lo siguiente:

  • Si es una corrección, es posible que un test unitario o UITest encaje y ayude a evitar regresiones en el futuro.
  • Si has añadido algo nuevo (por ejemplo, una propiedad nueva al Label), modifica Controls Gallery para reflejar la nueva opción.

El momento de enviar la PR

Añade un título descriptivo junto con una buena descripción (si hay cambios visuales o añadiste algun ejemplo o UITest, añade capturas de pantalla). Si has corregido una issue (o issues) añade el enlace a las mismas.

A continuación, si hay cambios en API añade los detalles. Por último, rellena el checklist indicando si hay UITests, etc.

Enviar PRs

Todo listo para enviar!. Una vez enviado, miembros del equipo así como de la comunidad comenzarán a revisar todo. Una vez pasadas revisiones, builds y otras validaciones. Enhorabuena, tus cambios estarán incluidos en Xamarin.Forms!.

Tras añadir tus cambios en una nueva release, aparecerás nombrado junto a todos los miembros de comunidad que han colaborado al lanzar la versión!.

Gracias

F100s

A la hora de abordar nueva funcionalidad es dificil saber por donde comenzar. Por ese motivo se ha creado la etiqueta F100. Bajo esta etiqueta encontrarás un listado de funcionalidad que cumplen una serie de características:

  • Suele tratarse de funcionalidad no muy amplia y con una buena especificación (explicación detallada, API definida, etc.).
  • El alcance esta bien definido. No hay que modificar o añadir un volumen alto de clases (normalmente).

F100

Si quieres añadir nueva funcionalidad, el listado de F100 es un gran punto de partida!.

Hasta aquí. Creo que hemos realizado un buen resumen de como contribuir en Xamarin.Forms. Además de todo lo expuesto, si puedo ayudar en algo tan solo avísame. Por otro lado, estoy pensando en la idea de hacer algun streaming en Twitch abordando este tema, ¿te resultaría interesante?. Cualquier feedback es bienvenido en los comentarios de la entrada!.

Más información

[Xamarin.Forms] Nueva versión de Xamanimation repleta de novedades

Xamanimation

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.

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.

Desde la versión anterior he recibido feedback, sugerencias y peticiones. Las principales son:

  • Poder retrasar animaciones.
  • Poder lanzar animaciones de forma indeterminada (repetir).
  • Poder gestionar facilmente animaciones dependiendes del valor de un scroll, carousel, etc.
  • Parallax.
  • Facilitar lanzar animaciones aún más desde XAML (más Triggers).
  • Transiciones. La principal petición esta relacionada con la navegación.

Peticiones

Con todas las sugerencias y peticiones, había motivos más que suficientes para una actualización de la librería. De esta forma, llega la versión 1.3 de Xamanimation.

Novedades

A continuación, vamos a repasar las novedades principales de la nueva actualización.

Retrasar animaciones

La primera opción añadida es la posibilidad de retrasar animaciones. Se ha incluido la propiedad Delay para poder indicar en milisegundos el tiempo a esperar antes de lanzar una animación.

Retrasar animaciones

Animaciones infinitas

Otra opción muy pedida es la posibilidad de repetir de forma indefinida animaciones. Casos muy típicos como un fondo animado o por ejemplo, en un reproductor de música girar el disco durante la reproducción.

Se ha añadido la propiedad RepeatForever de tipo bool.

Repetir animaciones

Nuevos triggers

Hasta ahora, podíamos crear una animación o StoryBoard y lanzar la animación con un Trigger al cambiar una propiedad o ejecutar un evento directamente desde XAML. Pero, ¿podemos simplificar este proceso?.

Ahora se cuenta con nuevos Triggers que simplifican la ejecución de animaciones.

Más Triggers!

Entre las opciones que tenemos disponibles:

  • AnimateInt
  • AnimateColor
  • AnimateCornerRadius
  • AnimateDouble
  • AnimateThickness

Dependiendo del tipo de de la propiedad, usaremos un Trigger u otro. El uso es sencillo. Indicamos:

  • TargetPropperty: La propiedad a animar.
  • To: El valor final de la propiedad que queremos animar.
  • Duration: Duración de la animación en milisegundos.
  • Delay: Si queremos retrasar la animación. De nuevo, se indica en milisegundos.

NOTA: La propiedad From ya tendrá el valor actual de la propiedad, no es necesario establecer el valor salvo que la animación se quiera realizar desde otro valor diferente.

Animaciones progresivas

De las peticiones recibidas, añadir animaciones progresivas era una de las más repetidas. Hablamos de casos donde animamos una propiedad en base a un valor específico que va cambiando en base a una interacción por parte del usuario.

Por ejemplo, animar propiedades de elementos al hacer scroll para conseguir efecto Parallax, cambiar tamaños de elementos, etc.

Animaciones progresivas

Entre las opciones que tenemos disponibles:

  • AnimateProgressInt
  • AnimateProgressColor
  • AnimateProgressCornerRadius
  • AnimateProgressDouble
  • AnimateProgressThickness

Dependiendo del tipo de de la propiedad, usaremos un Trigger u otro. El uso es sencillo. Indicamos:

  • TargetPropperty: La propiedad a animar.
  • Progress: La propiedad más importante. Es la responsable de controlar la animación.
  • Minimum: Cuando el valor de esta propiedad es igual al de Progress, comienza la animación.
  • Maximum: Cuando el valor de esta propiedad es igual al de Progress, la animación se detiene.
  • From: Valor inicial de la propiedad a animar.
  • To: El valor final de la propiedad que queremos animar.

Veamos un ejemplo para entenderlo mejor:

<xamanimation:AnimateProgressColor
     TargetProperty="VisualElement.BackgroundColor"
     Progress="{Binding ScrollY, Source={x:Reference ScrollBehavior}}" 
     Minimum="0"
     Maximum="200"
     From="Black"
     To="Red"/>

En este caso vamos a animar el color de fondo de un BoxView. El valor ira cambiando poco a poco segun el valor de ScrollY de un ScrollViewer pasando de negro a rojo segun el valor del scroll va aumentando hasta 200.

Transiciones

Otra opción muy solicitada va relacionada con el uso de transiciones. Se han añadido transiciones de entrada.

Este tipo de transición añade una transición en los controles cuando aparecen por primera vez. Puede usar esto en elementos individuales o en Layouts. En el último caso, los elementos hijos se animarán de forma secuencial en lugar de todos al mismo tiempo.

Transiciones de entrada

El uso es sencillo. Utilizamos EntranceTransition pudiendo controlar la duración.

Otros cambios

Además de los cambios anteriores:

  • Se ha actualizado todo a Xamarin.Forms 4.1.
  • El ejemplo hace uso de Shell y Visual ahora.
  • Se han añadido otros Triggers como por ejemplo, para detener animaciones.
  • Correciones menores.

¿Y en siguientes versiones?

Tengo algunas pruebas interesantes realizadas con la navegación. Una de las mejoras en la próxima versión estará relacionada con transiciones entre páginas además de añadir más tipos de transiciones.

Más información