[Xamarin.Forms] Ejemplos de Backend Linux

Introducción

Xamarin.Forms añade una capa de abstracción en la capa de UI que nos permite definir la misma una única vez para todas las plataformas. Podemos definir esta interfaz con código C# o XAML. El soporte de Linux (GTK) ahora está  disponible en Xamarin.Forms.

Xamarin.Forms

Para conocer y revisar las diferentes opciones disponibles, ¿algo mejor que contar con ejemplos?

Ejemplos Xamarin.Forms.Platform.GTK

El repositorio de ejemplos oficial de Xamarin.Forms es una fuente inmejorable de ejemplos cubriendo desde ejemplos básicos a uso de SkiaSharp, SQlite, gestos, efectos, etc. A continuación, puedes encontrar un repositorio donde encontrar la mayoría de ejemplos (y creciendo!) con versión GTK.

Puedes encontrar el repositorio en GitHub:

Ver GitHub

Más información

Anuncios

[Xamarin.Forms] Ejemplos de Backend WPF

Introducción

Xamarin.Forms añade una capa de abstracción en la capa de UI que nos permite definir la misma una única vez para todas las plataformas. Podemos definir esta interfaz con código C# o XAML. El soporte de WPF ahora está  disponible en Xamarin.Forms.

Xamarin.Forms

Para conocer y revisar las diferentes opciones disponibles, ¿algo mejor que contar con ejemplos?

Ejemplos Xamarin.Forms.Platform.WPF

El repositorio de ejemplos oficial de Xamarin.Forms es una fuente inmejorable de ejemplos cubriendo desde ejemplos básicos a uso de SkiaSharp, SQlite, gestos, efectos, etc. A continuación, puedes encontrar un repositorio donde encontrar la mayoría de ejemplos (y creciendo!) con versión WPF.

Puedes encontrar el repositorio en GitHub:

Ver GitHub

Más información

[Xamarin.Forms] Novedades de la versión 3.2 pre1 (Preview)

Introducción

Recientemente se ha liberado la primera Preview de la versión 3.2 de Xamarin.Forms. Una nueva versión repleta de novedades que vamos a revisar en este artículo.

Las mejoras principales

A continuación, vamos a revisar las novedades principales (no son todas).

Control de la posición del caret

Comenzamos revisando una novedad sencilla pero muy interesante, controlar la posición del Caret. Ahora contamos con una nueva propiedad de tipo entero llamada CursorPosition.

<Entry 
     CursorPosition="4"
     Text="CursorPosition"/>

También tenemos un Platform Specific en el caso de iOS para poder controlar el color del cursor Entry<iOS>.CursorColor.

Commandable Span regions

Ya contábamos con la propiedad FormattedText para poder crear texto con formato utilizando Spans. Ahora nos llega la posibilidad de añadir Gesture Recognizers a cada elemento.

<Label>
     <Label.FormattedText>
          <FormattedString>
               <Span Text="{Binding Span1}" />
               <Span 
                    Text="{Binding Span2}" 
                    TextColor="Blue">
                    <Span.GestureRecognizers>
                         <TapGestureRecognizer Command="{Binding TapCommand}" />
                    </Span.GestureRecognizers>
               </Span>
               <Span Text="{Binding Span3}"/>
          </FormattedString>
     </Label.FormattedText>
</Label>

El resultado:

Commandable Spans

Abre muchas posibilidades a crear enlaces, abrir otras Apps (enviar correo, etc.).

Bordes redondeados en BoxView

Vamos con otra novedad bastante requerida, bordes redondeandos en el control BoxView.

<BoxView 
     CornerRadius="24, 0, 24, 24"
     BackgroundColor="Red"
     Color="Red"
     HeightRequest="100"
     Margin="12, 0"/>

Contamos con la propiedad CornerRadius que permite establecer el valor del borde de cada esquina.

Bordes redondeados en BoxView

Paddings en botones

Añadida opción para controlar el Padding en botones:

<Button 
     Text="With Padding"
     Padding="6, 12, 48, 0"/>

La nueva propiedad Padding es de tipo Thickness.

Page TitleView

Estoy seguro que la siguiente novedad va a ahorrar más de un Custom Renderer. Estamos ante una propiedad adjunta llamada TitleView, como TitleIcon de la NavigationPage.

<NavigationPage.TitleView>
     <StackLayout>
          <Label 
               Text="TitleView"
               TextColor="White"
               FontSize="28"/>
          <Label 
               Text="I can be a subtitle"
               TextColor="White"/>
          <SearchBar 
               Placeholder="This is a SearchBar"
               PlaceholderColor="Black"
               BackgroundColor="White"
               HorizontalOptions="FillAndExpand"/>
     </StackLayout>
</NavigationPage.TitleView>

Podemos establecer el valor de TitleView en cada Page para personalinar el valor.

El resultado:

TitleView

Es posible establecer también el valor desde C#:

NavigationPage.SetTitleView(this, MyTitleView());

Nuevas propiedades Placeholder y PlaceholderColor en el Editor

Añadidas propiedades Placeholder y PlaceholderTextColor:

<Editor 
     Placeholder="This is the Placeholder"
     PlaceholderColor="Orange"/>

El resultado:

Placeholder en Editor

OnPlatform/OnIdiom markup extensions

Llega nueva extensión de marcado para simplificar la gestión de valores utilizados con OnPlatform u OnIdiom desde XAML.

¿El cambio?

Podemos pasar de:

<Label Text="This is nice!">
     <Label.FontSize>
          <OnPlatform x:TypeArguments="x:Double">
               <On Platform="iOS" Value="20" />
               <On Platform="Android" Value="24" />
               <On Platform="UWP" Value="28" />
          </OnPlatform>
     </Label.FontSize>
</Label>

A:

<Label 
     Text="This is nice!"
     FontSize="{OnPlatform Android=24, iOS=20, UWP=28}" />

SwipeGestureRecognizer

Dentro del conjunto de gestos disponibles en Xamarin.Forms, había uno que se echaba de menos, Swipe.

var swipe = new SwipeGestureRecognizer
{
     Direction = SwipeDirection.Left
};

swipe.Swiped += (sender, args) => 
{

};

Podemos detectar el gesto Swipe a izquierda, derecha, arriba y abajo.

Swipe!

Puedes encontrar el ejemplo en GitHub:

Ver GitHub

Más información

[Xamarin.Forms] Principales novedades de la versión 3.1

Introducción

Contamos con nueva versión de Xamarin.Forms, la 3.1. Una versión que tiene una variedad de novedades centradas en reducir la cantidad de controles personalizados y código específico en nuestras aplicaciones. En este artículo, vamos a hacer un rápido repaso sobre las novedades principales.

Novedades

Entre el conjunto de novedades principales encontramos:

Pestañas en la parte inferior

Google añadió BottomNavigationView en Android Support Library 25, y gracias a ello, ha sido posible añadirlo en Xamarin.Forms de forma sencilla utilizando Platform Specific.

<TabbedPage
     xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
     BarBackgroundColor="LightBlue"
     android:TabbedPage.ToolbarPlacement="Bottom"
     android:TabbedPage.BarItemColor="Gray"
     android:TabbedPage.BarSelectedItemColor="Black"
     Title="Bottom Tabs">
     <TabbedPage.Children>
          <ContentPage 
               Title="First"
               Icon="first">
               <Grid />
          </ContentPage>
          <ContentPage
               Title="Second"
               Icon="second">
               <Grid />
          </ContentPage>
          <ContentPage
               Title="Third"
               Icon="third">
               <Grid />
          </ContentPage>
     </TabbedPage.Children>
</TabbedPage>

Se puede establecer la posición de las pestañas con la propiedad ToolbarPlacement. También se cuentan con propiedades destinadas a personalizar el estilo de las pestañas:

  • BarItemColor: Color del icono y texto de cada pestaña.
  • BarSelectedItemColor: Color del icono y texto de la pestaña seleccionada.

Pestañas en la parte inferior

Auto-Resize Editor

Otra pequeña novedad bastante requerida. Según se va escribiendo en un control de tipo Editor, el control va creciendo automáticamente. Lo podemos conseguir gracias a la propiedad AutoSize que permite los siguientes valores:

  • Disabled: Valor por defecto. El control no crecerá.
  • TextChanges: El control crece automáticamente para permitir mostrar el contenido.
<Editor
     Text="AutoResize"
     AutoSize="TextChanges"/>

El resultado:

Autoresize Editor

Return key para Entry

Con la nueva propiedad ReturnType del Entry podemos modificar la apariencia del botón para completar la acción en el teclado virtual.

<Entry 
     ReturnType="Send"/>

Los valores posibles para ReturnType son:

  • Default
  • Done
  • Go
  • Next
  • Search
  • Send

El resultado:

Return Key

AutoCapitalization keyboard para el Entry

A veces en ciertos formularios no deseamos que el teclado automáticamente establezca la primera letra en mayúsculas. Por ejemplo, al introducir un correo electrónico. Ahora podemos controlar el comportamiento del teclado con KeyboardFlags:

<Entry 
     Placeholder="Insert text">
     <Entry.Keyboard>
          <Keyboard x:FactoryMethod="Create">
               <x:Arguments>
                    <KeyboardFlags>CapitalizeNone</KeyboardFlags>
               </x:Arguments>
          </Keyboard>
     </Entry.Keyboard>
</Entry>

Puedes consultar los valores posibles de KeyboardFlags en el siguiente enlace.

Auto Capitalization

Opciones de scrollbar Vertical y Horizontal

Se han añadido propiedades para controlar la visibilidad de las barras de scroll del ScrollView, tanto horizontal como vertical.

<ScrollView
     VerticalScrollBarVisibility="Always" 
     HorizontalScrollBarVisibility="Never">
</ScrollView>

Bindable Span

Otra novedad bastante interesante. Ahora podemos usar enlace a datos en Spans además de poder personalizar el color de cada Span:

<Label>
     <Label.FormattedText>
          <FormattedString>
               <FormattedString.Spans>
                    <Span Text="Test" />
                   <Span Text="{Binding Info}"
                         TextColor="Red" />
               </FormattedString.Spans>
          </FormattedString>
     </Label.FormattedText>
</Label>

Invocar JavaScript desde WebView

Ahora podemos invocar de forma sencilla código JavaScript desde el control WebView, utilizando una cadena con la posibilidad de obtener el valor de retorno.

string result = await EvaluateJsWebView.EvaluateJavaScriptAsync(
"var test = function(){ return 'This string came from Javascript'; }; test();");

Lo conseguimos con el nuevo método EvaluateJavaScriptAsync que evalua el código pasado como parámetro y retorno un valor siempre en formato de cadena.

Otros

Hay muchos más pequeños cambios como:

Puedes encontrar el ejemplo en GitHub:

Ver GitHub

Más información

[Xamarin.Forms] Addins y extensiones para Visual Studio macOS y Windows

Introducción

Visual Studio para macOS y Windows cuentan con modelos de extensión diferentes, modelos para crear interfaces de usuario diferentes y habitualmente trasladar un addin de macOS a una extension en Windows o viceversa, es costoso. ¿Podemos simplificar el proceso?, ¿podemos lograr compartir más elementos?.

En este artículo, vamos a ver como crear addins para Visual Studio macOS así como extensiones para Visual Studio Windows utilizando Xamarin.Forms para lograr compartir la UI.

Utilizaremos Measurer4000, herramienta diseñada para obtener métricas de código compartido en proyectos Xamarin. Nuestro objetivo será añadir la herramienta dentro de Visual Studio.

Add-ins para Visual Studio macOS

La arquitectura de Visual Studio para macOS es extensible. La forma de extender se basa en rutas de extensión que permiten que terceros extiendan el comportamiento. Por ejemplo: para extender la zona de edición de código, se expone /MonoDevelop/SourceEditor2/ContextMenu/Editor permitiendo añadir nuevos comandos en el menu contextual al hacer clic derecho.

AddIn Maker es un proyecto Open Source creado por Mikayla Hutchinson que permite el desarrollo y la depuración de add-ins para Visual Studio macOS desde Visual Studio macOS.

Para la gestión de la interfaz de usuario se utiliza GTK# o XWT.

Extensiones para Visual Studio Windows

En Windows tenemos la posibilidad de extender practicamente cualquier parte: menús, barras de herramientas, ventanas, etc.

Para crear extensiones se deben instalar las opciones de Desarrollo de extensiones de Visual Studio.

Extensiones en Windows

Para crear extensiones contamos con una plantilla de proyecto VSIX vacía que puede usar junto con las nuevas plantillas de elemento que crean extensiones de editor, ventanas de herramientas y comandos de menú.

Para la definición de la UI, utilizamos WPF.

Xamarin.Forms

Con la llegada de Xamarin.Forms 3.0 encontramos soporte a Linux gracias a un nuevo backend basado en GTK# además de un backend WPF.

Por lo que si usamos GTK# y WPF, ¿podríamos usar XAML y Xamarin.Forms para definir la UI de add-ins para Visual Studio tanto para macOS como para Windows?, ¿podría ser compartida?.

El proyecto en macOS

Comenzamos creando un proyecto de tipo IDE Extension:

IDE Extension

Este proyecto ya cuenta con la referencia a MonoDevelop.Addins. Continuamos añadiendo el paquete NuGet de Xamarin.Forms y Xamarin.Forms.Platform.GTK.

Para trabajar con Xamarin.Forms, debemos realizar la inicialización. La mejor opción para realizar esta tarea es realizarla nada más se abra el IDE. Para ello, vamos a crear un comando:

public class InitXamarinFormsCommand : CommandHandler
{
     protected override void Run()
     {
          Forms.Init();
     }
}

Y modificaremos el archivo Manifiest.addin.xml para añadir nuestro comando como punto de extensión en el arranque del IDE.

<Extension path="/MonoDevelop/Ide/StartupHandlers">
     <Class class="Measurer4000.Addin.Mac.Commands.InitXamarinFormsCommand"/>
</Extension>

Llega la hora de extender.

Añadimos otro punto de extensión:

<Extension path = "/MonoDevelop/Ide/MainMenu/Tools">
     <CommandItem id="Measurer4000.Addin.Mac.Commands.MeasurerCommand"/>
</Extension>

Fíjate que en esta ocasión, añadiremos un nuevo comando en el menu principal, opción herramientas.

Veamos la definición del comando:

public class MeasurerCommand : CommandHandler
{
     protected override void Update(CommandInfo info)
     {
          info.Visible = true;

          var projects = IdeApp.Workspace.GetAllProjects();

          if (projects.Any())
               info.Enabled = true;
          else
               info.Enabled = false;
     }

     protected override void Run()
     {
          new MeasurerWindow().Show();
     }
}

Comenzamos utilizando IdeApp. La clase estática MonoDevelop.Ide.IdeApp es su punto de entrada de extension de Visual Studio. Expone Workbench, Workspace, múltiples servicios  así como métodos relacionados con el ciclo de vida del IDE.

Habitualmente, la clase IdeApp se utiliza para acceder a Workbench o a Workspace. IdeApp.Wortkspace se usa para acceder al estado general del Ide durante una sesión de usuario. Podemos abrir nuevos proyectos y documentos, detectar archivos abiertos y mucho más.

En nuestro caso, lo utilizamos para detectar si el usuario tiene abierto al menos un proyecto.

En caso de abrir un proyecto, habilitamos la opción.

Al ejecutar el comando lanzamos una ventana llamada MeasurerWindow.

public class MeasurerWindow: Gtk.Window
{
     public MeasurerWindow()
     : base(Gtk.WindowType.Toplevel)
     {
          Title = "Measurer4000";
          WindowPosition = Gtk.WindowPosition.Center;

          var page = new MeasurerView();

          Add(page.CreateContainer());

          SetSizeRequest(800, 480);
     }
}

Es una ventana realizada con Gtk cuyo contenido utilizará una ContentPage de Xamarin.Forms. La clave para utilizar Xamarin.Forms es embeber el contenido. Tenemos disponible el método de extensión CreateContainer de Xamarin.Forms en el backend GTK para obtener la ContentPage como contenido nativo.

El proyecto en Windows

Comenzamos el proyecto en Windows añadiendo un comando.

Nuevo comando

Los menús y las barras de herramientas son la forma en que los usuarios acceden a los comandos en el VSPackage. Los comandos son funciones que realizan tareas, como mostrar una ventana o crear un nuevo archivo. Los menús y barras de herramientas son formas gráficas convenientes para presentar los comandos a los usuarios.

En este comando realizamos la inicializacion de Xamarin.Forms:

public static void Initialize(Package package)
{
     Instance = new MeasurerCommand(package);

     Forms.Init();
}

Al ejecutar el comando:

private void MenuItemCallback(object sender, EventArgs e)
{
     var measurerWindow = new MeasurerWindow();

     var measurerContent = new MeasurerView().ToFrameworkElement();
     measurerWindow.Content = measurerContent;

     measurerWindow.Show();
}

Lanzamos una ventana llamada MeasurerWindow (al igual que ya hacíamos en macOS), ventana WPF cuyo contenido es una ContentPage de Xamarin.Forms. La clave para utilizar Xamarin.Forms es de nuevo embeber el contenido. Tenemos disponible el método de extensión ToFrameworkElement de Xamarin.Forms en el backend WPF para obtener la ContentPage como contenido nativo.

La ventana:

<Window 
     x:Class="Measurer4000.Addin.Windows.Windows.MeasurerWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     WindowStartupLocation="CenterScreen"
     Title="Measurer 4000">
     <Grid>

     </Grid>
</Window>

UI XAML compartida

Tanto en macOS como en Windows utilizamos una ContentPage para definir la interfaz de usuario. Hablamos de una interfaz definida en XAML que puede ser compartida en macOS y Windows, donde en cada plataforma, se utilizará un backend diferente para renderizar la UI con GTK# en el caso de macOS y con WPF en el caso de Windows.

<Grid>
     <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition Height="*" />
          <RowDefinition Height="Auto" />
     </Grid.RowDefinitions>
     <Grid Grid.Row="0"
          Margin="24">
          <Grid.ColumnDefinitions>
               <ColumnDefinition />
               <ColumnDefinition />
               <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <StackLayout Grid.Column="0">
          <StackLayout Orientation="Vertical"
               HorizontalOptions="Center"
               Margin="0, 24, 0, 0">
               <Label Text="iOS Specific Code" />
               <Label Text="{Binding Stats.iOSSpecificCode}"
                    FontSize="30" />
          </StackLayout>
          <StackLayout Orientation="Vertical"
               HorizontalOptions="Center"
               Margin="0, 24, 0, 0">
               <Label Text="Share code in iOS" />
               <Label Text="{Binding Stats.ShareCodeIniOS}"
                    FontSize="30" />
          </StackLayout>
     </StackLayout>
     ...

En la interfaz utilizaremos algunos Labels donde msotrar información con cantidad de líneas así como porcentajes de código compartido y código específico. Por otro lado, utilizamos Oxyplot para mostrar gráficos de tipo tarta.

public MeasurerView()
{
     InitializeComponent();

     BindingContext = new CustomMainViewModel();
}

Toda la lógica del addin, modelos, ViewModels, etc. es la ya existente en la herramienta. Utilizaremos MVVM de exactamente la misma forma utilizada para crear Apps, en nuestro addin. En la ViewModel es necesario pasar la ruta de la solución para que pueda analizar y obtener toda la información.

En macOS tenemos en IdeApp.Workspace lo necesario para obtener la información necesaria de la solución con la que trabaja el usuario. Podemos obtener el listado de soluciones con el metodo GetAllSolutions.

var solutionPath = Path.Combine(Directory.GetCurrentDirectory(), solution.FileName);
_viewModel.MeasureSolutionByPath(solutionPath);

En el caso de Windows, obtenemos la instancia del objeto DTE (Development Tools Environment). DTE representa el entorno de desarrollo integrado (IDE) de Visual Studio y es el objeto de máximo nivel en la jerarquía. Nos otorga acceso a una gran variedad de propiedad y métodos para obtener información de la solución, propiedades, ventanas, etc.

var solution = ((DTE)ServiceProvider.GlobalProvider.GetService(typeof(DTE))).Solution;
var solutionPath = solution.FullName;
_viewModel.MeasureSolutionByPath(solutionPath);

Accedemos a la solución, y extraemos la ruta a la misma.

El resultado en macOS:

Addin en macOS

Y en Windows:

Addin en Windows

¿Qué te parece?. Quizás en un futuro sea una opción a la hora de extender Visual Studio. Ahora que tenemos el IDE en más de un sistema operativo, es hora de pensar en contar con una opción para crear extensiones que compartan la mayor cantidad de código posible.

Más información

[Xamarin.Forms] Bottom TabbedPage para Android

Xamarin.Forms 3.1

Con la llegada de Xamarin.Forms 3.1 llegan una gran cantidad de mejoras y correcciones (es genial ver que muchas vienen de la comunidad). Entre el conjunto de novedades tenemos la posibilidad de crear TabbedPage en la parte inferior en Android.

En este artículo, vamos a ver como crear una Bottom TabbedPage.

Bottom TabbedPage

Podemos crear una TabbedPage con posición en la parte inferior de forma muy sencilla en Android utilizando platform specific:

On<Xamarin.Forms.PlatformConfiguration.Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);

El resultado:

Bottom TabbedPage

Tienes un ejemplo disponible en GitHub:

Ver GitHub

Más información

[Xamarin.Forms] Novedades utilizando Resource Dictionaries

Resource Dictionaries

En toda aplicación móvil la apariencia visual es vital. Cada vez es mayor el esfuerzo depositado a la hora de crear aplicaciones atractivas a la par que intuitivas y en muchos casos conseguir una imagen única que diferencia a la Aplicación del resto es prioritario. Por este motivo, debemos de contar con opciones sencillas de poder personalizar los distintos elementos que componen la interfaz.

Los estilos permitir definir múltiples propiedades visuales de elementos de la interfaz de forma reutilizable.

Los recursos XAML son objetos que podemos reutilizar más de una vez. Hablamos desde un sencillo color o tamaño de fuente, a el uso de estilos. Los diccionarios de recursos o ResourceDictionaries permiten definir una zona donde definir recursos.

Hasta ahora…

Podíamos definir diccionarios de recursos en archivos totalmente independientes. Hablamos de una clase derivada de ResourceDictionary, que consta de un par de archivos. Por un lado tenemos el archivo XAML donde se definen los recursos y por otro lado, la clase subyacente encarga de realizar InitializeComponent.

NOTA: Para crear un archivo de tipo ResourceDictionary, crea una ContentPage o ContentView y renombra la clase base de ContentPage o ContentView a ResourceDictionary.

Veamos un ejemplo.

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     x:Class="ResourceDictionaries.MyResourceDictionary">

     <Style x:Key="LabelStyle"
          TargetType="Label">
          <Setter Property="TextColor"
               Value="Red" />
          <Setter Property="FontSize"
               Value="24" />
</Style>

</ResourceDictionary>

NOTA: Fíjate que utilizamos x:Class para establecer la clase subyacente necesaria.

Para utilizar el diccionario de recursos, creamos una instancia:

<ContentPage.Resources>
     <local:MyResourceDictionary />
</ContentPage.Resources>

La forma anterior de añadir el diccionario de recursos a pesar de ser válida es muy limitada ya que sólo nos permite utilizar los recursos del diccionario instanciado. Podríamos necesitar utilizar mñas de un diccionario de recursos o añadir otros recursos.

Para solucionar este problema, tenemos disponible la posibilidad de utilizar diccionarios de recursos combinados.

<ContentPage.Resources>
     <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
               <local:MyResourceDictionary />
          </ResourceDictionary.MergedDictionaries>
     </ResourceDictionary>
</ContentPage.Resources>

Podemos combinar varias instancias de diccionarios de recursos en uno existente. Se puede realizar directamente desde XAML utilizando la propiedad MergedDictionaries.

Con la llegada de Xamarin.Forms 3.0

La combinación de ResourceDictionary se simplifica con la llegada de Xamarin.Forms 3.0. Por un lado, ya no es necesario utlizar las etiquetas MergedDictionaries ya que en su lugar, podemos agregar directamente otro ResourceDictionary utilizando la propiedad Source.

Además, Xamarin.Forms 3.0 crea automáticamente una instancia de ResourceDictionary por lo que ya no es necesario añadir estas etiquetas.

<ContentPage.Resources>
     <ResourceDictionary Source="MyResourceDictionary.xaml" />
</ContentPage.Resources>

Esta nueva sintaxis no crea una instancia del diccionario de recursos. Gracias a este cambio, ya no es necesario mantener la clase subyacente o code behind del diccionario de recursos (MyResourceDictionary.xaml.cs) por lo que podemos borrarlo además del atributo x:Class de la ráiz del diccionario.

Más simple y sencillo!

Puedes encontrar un ejemplo en GitHub:

Ver GitHub

Más información

[Material DotNet2018] Xamarin.Forms Everywhere

El evento

El pasado 29 de Mayo tenía lugar la DotNet2018. Un gran día repleto de sesiones técnicas cubriendo todo el espectro de tecnologías .NET, desde Xamarin, Azure, IoT, VR, etc.

Fue un día genial de grandes sesiones pero también de encontrarte con grandes amigos, desvirtualizar a nuevos amigos, networking, etc. 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 algo tan grande y complejo fluyese de forma tan natural y sencilla.

El material

He tenido en placer de poder participar en el evento con una sesión acerca de Xamarin.Forms y nuevas plataformas o posibilidades.

Comenzamos el evento revisando Xamarin.Forms en Linux:

Xamarin.Forms en Linux

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Continuamos viendo estado y opciones de Xamarin.Forms en WPF:

Xamarin.Forms WPF

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Y continuamos con nuevos backends de Xamarin.Forms, y en esta ocasión hablamos de Ooui de Frank Krueger.

Desde el navegador!

Repasamos estado, un poco de WebAssembly y continuamos. Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHubContinuamos viendo los primeros pasos del backend de Windows Forms y dimos paso a nuevas posibilidades.

Hablamos de wearables y Tizen.CircularUI, donde repasamos opciones principales, etc.

Posteriormente llegço el turno de IoT. Tras una breve introducción a Xamarin.IoT vimos como ya contamos con plantillas de proyectos e integración entre Xamarin.Forms (backend GTK#) con Xamarin.IoT.

Monitor de temperatura realizado con Xamarin.IoT y Xamarin.Forms

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Tras ver nuevas plataformas o dispositivos con IoT o Wearables, nos centramos en nuevas posibilidades en UI. Hicimos un repaso de:

  • VisualStateManager
  • FexLayout
  • SkiaSharp
  • Etc

En este punto, vimos como crear interfaces combinadas con elementos 3D con Wave Engine o como combinar ARCore con Xamarin.Forms creando Custom Renderers.

ARCore

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Completamos el evento utilizando Xamarin.Forms para crear la UI de addins para Visual Studio en Windows y macOS.

El ejemplo:

Ver GitHub

Hasta el año próximo!

Y ya tenemos evento confirmado para el próximo año!. Apunta la fecha, 23 de Mayo.

DotNet 2019!

Allí nos vemos!

Más información

[Xamarin.Forms] Aplicaciones con contenido 3D utilizando Wave Engine

Introducción

A la hora de desarrollar aplicaciones móviles, nos encontramos con una enorme variedad de requisitos a nivel visual y de contenido. En Xamarin.Forms gracias al avance en novedades (pestañas en la parte inferior, bordes redondeados, etc.) junto a SkiaSharp, estilos, efectos y Custom Renderers otorgan grandes opciones para desarrollar aplicaciones visualmente atractivas.

En determinadas ocasiones, la visualización e interacción con elementos 3D o cámaras en 360 grados por ejemplo, otorga una mejor experiencia en nuestras aplicaciones. Por ejemplo, la visualización de edificios y diferentes plantas o la previsulización de un coche que deseamos comprar. Para conseguir la visualización e integración con elementos 3D tenemos diferentes opciones como Urho o Wave Engine.

En este artículo, vamos a ver como integrar elementos 3D en una aplicación Xamarin.Forms utilizando Wave Engine.

Wave Engine

Wave Engine es un motor de videojuegos 2D y 3D multiplataforma, basado en componentes y totalmente gratuito (no hay licencias ni tampoco ningún tipo de royalty). Nos ofrece una API para trabajar con físicas, animaciones, sonido, etc. utilizando C# sin tener que profundizar a más bajo nivel y tener que trabajar con DirectX directamente.

Podemos desarrollar para Android, iOS, Linux, macOS, Windows, etc..

Creando la escena 3D

Vamos a realizar un ejemplo sencillo pero suficientemente interesante para conocer:

  • La creación de una escena 3D.
  • Integrar una escena 3D en Xamarin.Forms.
  • Interactuar desde una vista XAML de Xamarin.Forms con la escena 3D.

Crearemos una escena con un coche y podremos modificar el color del mismo desde un ListView de Xamarin.Forms.

¿Y de dónde obtenemos el modelo 3D?

Para este ejemplo, vamos a utilizar un modelo 3D totalmente gratuito de Sketchfab gracias a Karol Miklas.

Sketchfab

Tras descargar el modelo 3D, arrancamos el editor de Wave Engine.

Editor Wave Engine

NOTA: Puedes descargar Wave Engine desde este enlace.

Creamos nuevo proyecto, y arrastramos el modelo descargado a la carpeta Assets en el apartado Assets Details. Podemos hacer doble clic en el archivo fbx para asegurar que todo es correcto.

Cargar el modelo

Comenzamos a montar nuestra escena arrastrando el modelo que acabamos de previsualizar desde Assets Details a la Scene:

Creando la escena

Llegados a este punto, tenemos suficiente. Podemos mejorar la escena con pequeños cambios como:

  • Añadir entidad plano 3D para ele suelo.
  • Añadir una esfera en forma de cúpula, para añadir “límites” al escenario.
  • Añadir más luces a la añadida por defecto.
  • Etc.

Integrando la escena con proyecto Xamarin.Forms

De momento, tenemos un proyecto Windows (proyecto creado por defecto) con nuestra escena. Podemos lanzar y probar nuestro proyecto.

Ejemplo en Windows

Pero…¿y cómo llegamos a integrarlo todo en Xamarin.Forms?. Wave Engine es un motor multiplataforma. Se pueden crear proyectos para plataformas como Android, iOS, UWP, Linux o macOS. Entre las diferentes opciones, para Android, iOS y UWP hay proyectos con integración con Xamarin.Forms.

Desde el editor de Wave Engine, Edit > Project Properties…

Nuevo perfil

Podemos elegir entre diferentes plataformas, y en cada plataforma diferentes Launchers. En Android, iOS y UWP contamos con Launcher Xamarin.Forms.

Xamarin.Forms

Esto nos crea automáticamente un nuevo proyecto utilizando Xamarin.Forms.

Estructura del proyecto

Tenemos una proyecto Shared con toda la lógica compartida de Wave Engine (escenas, behaviors, componentes, etc.) y otro proyecto de igual tipo donde tenemos la aplicación Xamarin.Forms con las vistas, etc.

Al final, trabajamos con una aplicación Xamarin.Forms habitual donde la carga de la escena 3D se realiza vía Custom Renderer. Contamos con el siguiente control:

public class WaveEngineSurface : View, IViewController
{
     public static readonly BindableProperty GameProperty = BindableProperty.Create(
     propertyName: "Game",
     returnType: typeof(IGame),
     declaringType: typeof(WaveEngineSurface),
     defaultValue: null);

     public IGame Game
     {
          get { return (IGame)GetValue(GameProperty); }
          set { SetValue(GameProperty, value); }
     }
}

Desde una vista XAML:

<AbsoluteLayout>
     <controls:WaveEngineSurface x:Name="WaveEngineSurface"
          AbsoluteLayout.LayoutFlags="All"
          AbsoluteLayout.LayoutBounds="0, 0, 1, 1" />
</AbsoluteLayout>

Interacción con la escena 3D

En este ejemplo, vamos a utilizar SlideOverKit para añadir un menu lateral deslizante, donde mostrar un listado de colores. La idea es permitir cambiar el color de coche en 3D. Pero para conseguirlo, necesitaremos interaccionar con la escena 3D desde nuestra aplicación Xamarin.Forms, ¿cómo lo hacemos?.

Al seleccionar cualquir color, lanzamos un comando en la ViewModel:

public ICommand ColorTappedCommand => new Command<CustomColor>(ChooseColor);

private void ChooseColor(CustomColor color)
{
     // TODO:
}

Al crear el proyecto Xamarin.Forms desde el editor visual tenemos una clase llamada WaveEngineFacade. Desde esta clase tenemos la opción de acceder a la escena. Creamos un método llamado UpdateColor. En el método debemos acceder a la entidad del coche, en concreto a su material, y modificar el color.

¿Cómo sabemos cual es esa entidad?.

Desde el editor, vemos el desglose de entidades (piezas) que componen al coche. Seleccionamos la carrocería y elegimos la opción Copy EntityPath:

Copy EntityPath

public static void UpdateColor(CustomColor color)
{
     var entity = _scene.EntityManager.Find("car.Plane_036.Plane_041");
     var materialComponent = entity.FindComponent<MaterialComponent>();
     var hex = color.Hex;
     ((StandardMaterial)materialComponent.Material).DiffuseColor = FromHex(hex);
}

NOTA: En la variable _scene tenemos acceso a cualquier elemento de la escena (cámara, luces, entidades, etc.). Utilizamos un método Initialize lanzado en el arranque de la aplicación para establecer el valor de la variable.

Desde el comando sencillamente lanzamos nuestro método:

WaveEngineFacade.UpdateColor(color);

El resultado final:

El resultado

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Más información

Primer vistazo a Xamarin Live Reload

Introducción

Xamarin.Forms es un toolkit que crea una abstracción sobre la interfaz de usuario de Android, iOS, Tize, WPF, macOS, Linux y Windows permitiendo desarrollarla una única vez con código C# o Extensible Application Markup Language (XAML).

A la hora de trabajar con la interfaz de usuario, tenemos grandes herramientas como IntelliSense en XAML, Previewer o Xamarin Live Player. Sin embargo, las dos últimas opciones no soportan todas las características que se pueden utilizar en una aplicación móvil lo que provoca errores al renderizar y previsualizar el contenido. Por este motivo, tenemos algunas grandes herramientas por parte de la comunidad Xamarin como Live XAML o Gorilla Player.

En este artículo, vamos a conocer Xamarin Live Reload, nueva herramienta oficial que nos permite ver cualquier cambio de XAML al vuelo.

Xamarin Live Reload

El objetivo principal de Xamarin Live Reload es permitir ver cualquier cambio relacionado con la interfaz de usuario de forma rápida y sencillo, soportando cambios al vuelo sin necesidad de compilar y desplegar. Cualquier cambio en XAML será reflejado de forma automática manteniendo los cambios.

La clave fundamental de esta nueva herramienta es que soporta cualquier librería, control de terceros además de Custom Renderers o efectos. A la hora de ver la previsualización, podemos utilizar emuladores o dispositivos físicos.

Instalación

Para poder instalar Live Reload necesitamos los siguientes requisitos:

Bastará con descargar e instalar la siguiente extensión:

Instalar Xamarin Live Reload

Instalamos…

Live Reload

Tras instalar la herramienta es hora de configurar nuestra App para utilizarla. Es tarea sencilla ya que solo tendremos que añadir el paquete NuGet Xamarin.LiveReload a nuestra librería .NET Standard 2.0.

Xamarin.LiveReload

NOTA: Es necesario utilizar .NET Standard para utilizar Live Reload en estos momentos.

Para completar la configuración y utilizar la herramienta en nuestra aplicación, en la clase App.xaml.cs debemos añadir:

 LiveReload.Init();

En el punto de entrada de la misma, es decir, en el constructor.

Todo preparado!

Utilizando la herramienta

Tras crear un proyecto Xamarin.Forms y lanzarlo en depuración en el emulador vemos lo siguiente:

Comenzamos a usar Live Reload

Visual Studio nos indica (parte superior) que Live Reload esta funcionando en un emulador de Android. A partir de este momento, cualquier cambio será aplicado:

Live Reload en acción!

A tener en cuenta…

  • Live Reload funciona con XAML. Cualquier cambio en C# requiere recompilación.
  • Se soportan las plataformas soportadas por Xamarin.Forms.
  • No se soportan (por ahora) estilos CSS.
  • Sólo funciona utilizando librerías .NET Standard.
  • Se puede utilizar en emuladores o dispositivos.
  • No hay límite en el número de dispositivos a utilizar.
  • Si no se cambia la configuración de Live Reload ni tampoco la máquina donde se compiló el código, no es necesario desplegar de nuevo. Basta con abror la aplicación previamente desplegada, conectar y continuar.

Más información