Número especial de Connect(); de 2018

Volumen 33, número 13

Desarrollo multiplataforma: Introducción al shell de Xamarin.Forms

Por David Ortinau; de 2018

Xamarin.Forms es uno de los kits de herramientas preferidos para los desarrolladores multiplataforma a quienes les gusta XAML y C#, ya que maximiza el uso compartido del código y, al mismo tiempo, proporciona acceso completo a todos los controles de UI y API nativos de la plataforma. Esta funcionalidad comprende tecnologías y conceptos que pueden resultar estimulantes y confusos al principio. La verdad es que algunos desarrolladores consideran frustrante el comienzo. Eligió Xamarin para ser productivo, y lo último que quiere es encontrarse con dificultades. Este año, en Connect();, estamos encantados de presentar el shell de Xamarin.Forms, un nuevo punto de partida predeterminado para el desarrollo de aplicaciones móviles que reduce la complejidad y aumenta la productividad.

Tal como sugiere su nombre, el shell es, básicamente, un contenedor que se encarga de las características básicas de la interfaz de usuario que necesita cada aplicación para que pueda centrarse en el trabajo principal de su aplicación. Las aplicaciones existentes para iOS y Android también pueden adoptar el shell fácilmente, y beneficiarse inmediatamente de las mejoras para la navegación, el rendimiento de la interfaz de usuario y la extensibilidad. El shell ofrece las siguientes ventajas:

  • Un sitio único para describir la estructura visual de las aplicaciones
  • Una UI de navegación común y un servicio de navegación omnipresente con vinculación en profundidad
  • Un controlador de búsqueda integrado para mejorar la experiencia general de búsqueda en la aplicación
  • Una filosofía extensible de forma predeterminada para agregar más flexibilidad y versatilidad

La aplicación

Al principio de cada proyecto, alguien esboza la estructura de la aplicación que deberá generar (con suerte, no solo en su cabeza). A veces se trata de una composición de diseño; otras, solo está dibujada en un papel. Con el shell, es muy fácil usar el contenido y trasladarlo a un contenedor de aplicaciones en ejecución listo para que alguien lo llene de contenido y funcionalidad.

En este artículo, usaré el ejemplo de una aplicación de compra móvil denominada Tailwind Traders. Se trata de una nueva aplicación de referencia que ha creado el equipo para mostrar cómo puede usar el shell de Xamarin.Forms, Azure, Cognitive Services, y otras características y servicios. Eche un vistazo a las composiciones de diseño proporcionadas por nuestro fantástico equipo de diseño en la Figura 1.

Composiciones de diseño para la aplicación de ejemplo Tailwind Traders
Figura 1 Composiciones de diseño para la aplicación de ejemplo Tailwind Traders

Como puede ver en las pantallas mostradas, la aplicación proporciona toda la funcionalidad obvia que necesita, incluido el flujo de inicio de sesión y registro, una experiencia de exploración con categorías de productos y búsqueda, y un flujo de finalización de la compra. Esta aplicación también aprovecha la cámara del dispositivo y la eficacia de Azure Custom Vision API para identificar productos en tiempo real.

Inicio rápido

Vamos a aplicar scaffolding a esta aplicación mediante el shell. Abra Visual Studio 2019 e inicie una nueva aplicación multiplataforma con Xamarin.Forms. Para los fines de este artículo y para comprender el potencial del shell, vamos a comenzar con un proyecto en blanco y a crear la estructura de la aplicación Tailwind Traders.

Una vez generados los archivos de proyecto, abra App.xaml.cs y observe que MainPage se define en una nueva instancia del shell. (Puede descargar las plantillas del shell desde aka.ms/xf-shell-templates). Estructuralmente, esta es la única diferencia de una aplicación típica de Xamarin.Forms que pueda haber visto en el pasado. Este es el código:

namespace TailwindTraders.Mobile
{
  public partial class App
  {
    public App()
    {
      InitializeComponent();
      MainPage = new AppShell();
    }
  }
}

Abra AppShell.xaml en la raíz de su proyecto de biblioteca de .NET Standard, como se muestra en la Figura 2.

Figura 2 Shell.xaml de una sola página

<?xml version="1.0" encoding="UTF-8"?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:TailwindTraders"
       RouteHost="tailwindtraders.com"
       RouteScheme="app"
       FlyoutBehavior="Disabled"
       Title="TailwindTraders"
       x:Class=" TailwindTraders.AppShell">
  <ShellItem>
    <ShellSection>
      <ShellContent>
        <local:MainPage/>
      </ShellContent>
    </ShellSection>
  <ShellItem>
</Shell>

Desglosemos los elementos de este archivo. Un shell consta de tres elementos jerárquicos: ShellItems, ShellSections y ShellContent. Cada elemento ShellContent es un elemento secundario de ShellSection, que, a su vez, es un elemento secundario de ShellItem: todo forma parte del shell. Ninguno de ellos por sí mismo representa la UI, sino la organización de la arquitectura de la aplicación. El shell toma estos elementos y produce la UI de navegación adecuada para la plataforma en que se ejecuta:

  • ShellItem: estructura de nivel superior de la aplicación representada por un elemento del control flotante. Puede contener varios elementos ShellSection.
  • ShellSection: agrupación de contenido de la aplicación navegable mediante pestañas inferiores. Puede contener uno o más elementos ShellContent, varios de ellos navegables mediante pestañas superiores.
  • ShellContent: instancias de ContentPages de la aplicación.

Puedo usar estos tres elementos para describir la estructura visual de la aplicación móvil Tailwind Traders. A continuación, ignoraré el flujo de inicio de sesión y registro, y agregaré varias instancias de ShellItem para hospedar contenido, representadas con un menú flotante a la izquierda.

¿Por qué no usar nombres como FlyoutItem, BottomTab o TopTab para conceptos del shell? Nuestro equipo de Microsoft ha tenido muchos debates al respecto y considera que Xamarin.Forms se ajusta a plataformas conocidas y futuras que, a veces, no comparten los conceptos exactos de pestañas o menús. Al usar una nomenclatura abstracta, le permitimos decidir mediante estilos y plantillas si estos elementos se deben representar de un modo coherente entre distintas plataformas o si se deben adherir a la estética de diseño de cada plataforma. Por supuesto, sus comentarios al respecto siempre son bienvenidos.

En la Figura 3 se muestra un ejemplo. Aquí verá un menú en el control flotante (los dos tercios inferiores de la UI) que se rellena automáticamente con elementos ShellItem. Esto le permite navegar a las diferentes áreas de la aplicación. Además de estos elementos, puede agregar explícitamente elementos de menú que no estén asociados con ninguna instancia de ShellItem. El encabezado de control flotante de la parte superior (los dos botones) presenta un contenido especial que consta de lo que quiera presentar en ese espacio. Para declarar un elemento FlyoutHeader personalizado en Shell.xaml, use este código:

<Shell.FlyoutHeader>
  <local:FlyoutHeader />
</Shell.FlyoutHeader>

Elementos de FlyoutMenu
Figura 3 Elementos de FlyoutMenu

El elemento de encabezado permite controlar cómo se comporta cuando los usuarios se desplazan por la pantalla. Hay tres opciones:

  • Fixed: el encabezado permanece fijo mientras se desplaza el contenido inferior.
  • Scroll: se desplaza con los elementos de menú.
  • CollapseOnScroll: se contrae de forma paralela mientras se desplaza.

Para ajustar este comportamiento, establezca la propiedad FlyoutHeaderBehavior del shell en el valor deseado detallado previamente. Por ahora, lo corregiremos con el código siguiente:

<Shell
  x:Class="TailwindTraders.Mobile.Features.Shell.Shell"
  FlyoutHeaderBehavior="Fixed"  
  ...            
  >             
  ...            
</Shell>

A continuación, vamos a configurar el contenido. Observando el diseño, puedo ver que hay una pantalla principal, una serie de categorías de producto, un perfil y, por último, una pantalla de cierre de sesión. Empecemos con la pantalla principal, con el código XAML siguiente:

<ShellItem Title="Home">
  <ShellSection>
    <ShellContent>
      <local:HomePage />
    </ShellContent>
  </ShellSection>
</ShellItem>

He desglosado este XAML de dentro hacia afuera, he agregado el elemento HomePage a la aplicación, que será el primer elemento ContentPage que aparecerá, pues es el primer contenido declarado en el archivo del shell. Se trata del mismo tipo de elemento ContentPage que usa en sus aplicaciones existentes de Xamarin.Forms, que ahora se hospedan en un contexto del shell.

Para este diseño solo necesito definir un título, pero ShellItem también proporciona la propiedad FlyoutIcon, que permite proporcionar una imagen para mostrarla a la izquierda del elemento. Los iconos pueden ser cualquier elemento ImageSource de Xamarin.Forms.

A continuación, ejecute la aplicación. En la página principal, haga clic en el icono de hamburguesa para abrir el menú flotante. Al pulsar en este elemento de menú, se desplaza a la pantalla principal (que, actualmente es la única pantalla). Vamos a empezar a trabajar y a agregar más cosas.

A continuación, implementaré las categorías de productos, como "Adornos de fiestas", "Dispositivos" y similares. Puedo agregar instancias de ShellItem para cada uno de ellos, pero, dado que las páginas de categoría de producto son la misma página con contenido distinto, puedo hacerlo de un modo inteligente. Usaré un elemento MenuItem sencillo para navegar a la misma página y pasaré datos mediante CommandParameter para evitar la duplicación innecesaria de páginas. Este es el código para agregar un elemento MenuItem en Shell.xaml:

<Shell.MenuItems>
  <MenuItem
    Command="{Binding ProductTypeCommand}"
    CommandParameter="1"
    Text="Holiday decorations" />
</Shell.MenuItems>

Una característica excelente del shell es que admite enlaces de datos. En este caso, tengo un comando en un modelo de vista que puede ejecutar la navegación. Del mismo modo que los elementos ShellItem, los elementos MenuItem tienen texto y un icono. Además, como los elementos ShellItem, puedo proporcionar estilos o incluso una plantilla personalizada para personalizar aún más el diseño estableciendo la propiedad MenuItemTemplate en el shell.

Puedo agregar más elementos de menú para cada categoría para completar la tarea. La Figura 4 muestra el código para todos los elementos de menú, mientras que la Figura 5 muestra el resultado visual en el menú flotante de la aplicación.

Figura 4 Todos los elementos de menú

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
  x:Class="TailwindTraders.AppShell"
  FlyoutHeaderBehavior="Fixed"
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:local="clr-namespace:TailwindTraders.Views"
  Title="Tailwind Traders"
  x:Name="theShell"
  Route="tailwindtraders"
  RouteHost="microsoft.com"
  RouteScheme="app">
  <Shell.MenuItems>
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="1"
      Text="Holiday decorations" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="2"
      Text="Appliances" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="3"
      Text="Bathrooms" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="4"
      Text="Doors &amp; Windows" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="5"
      Text="Flooring" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="6"
      Text="Kitchen" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="7"
      Text="Storage" />
  </Shell.MenuItems>
  <ShellItem Title="Home">
    <ShellSection>
      <ShellContent>
        <local:HomePage />
      </ShellContent>
    </ShellSection>
  </ShellItem>
</Shell>

Control flotante con todos los elementos de menú
Figura 5 Control flotante con todos los elementos de menú

Agregar más páginas

Ahora, agreguemos la página de perfil del diseño a nuestra aplicación. Agregue un nuevo elemento ContentPage al proyecto y, a continuación, vuelva al archivo Shell.xaml. Puede copiar el código XAML (que se muestra en la Figura 4) utilizado para la página HomePage y reemplazarlo con la página Profile, pero se arriesga a atascar la aplicación porque la página HomePage se crea inmediatamente al iniciar la aplicación. Para evitar que todas las páginas de la aplicación se carguen a la vez, uso una plantilla de datos, como se muestra a continuación:

<ShellContent
  Title="Profile"
  ContentTemplate="{DataTemplate local:ProfilePage}" />

En lugar de proporcionar ContentPage directamente en la propiedad de contenido de ShellContent, proporciono una plantilla de datos. Cuando el usuario navega a una pantalla, el shell crea una instancia de la página solicitada dinámicamente.

Hay que destacar que, con este tratamiento, en comparación con HomePage, he omitido los contenedores ShellItem y ShellSection, y he colocado el título directamente en ShellContent. Esto es mucho menos detallado y el shell sabe cómo controlarlo por mí, proporcionando los contenedores lógicos necesarios. También es importante tener en cuenta que estos contenedores no agregan vistas de UI al árbol. El shell se escribe con la velocidad de representación y el consumo de memoria en mente. Como resultado, el impacto sobre el rendimiento en el sistema operativo Android es bajo, ya que se hospeda el mismo contenido y UI que tiene actualmente dentro de este nuevo contexto de shell. Por supuesto, sigue siendo el responsable de la arquitectura interna de sus aplicaciones, pero el shell ofrece un excelente punto de partida.

Aplicar estilos al control flotante

Puede aplicar estilos a los aspectos del shell y FlyoutMenu como lo haría con cualquier otro elemento XAML que use estilos CSS o XAML. ¿Qué ocurre si quiere ir más allá respecto a cómo aparece el elemento de menú flotante? Si volvemos al diseño de la Figura 3, los elementos de menú son más oscuros que el resto de elementos del shell.

La presentación de los elementos de menú y de shell es extensible: solo tiene que proporcionar un elemento DataTemplate al shell. Un elemento MenuItem se representa en el menú flotante mediante la plantilla MenuItemTemplate del shell, y un elemento ShellItem se representa mediante una plantilla ItemTemplate. Para tener control total sobre el aspecto, defina cada propiedad en una plantilla DataTemplate que contenga un elemento ContentView personalizado. El shell proporcionará las propiedades enlazables Title y Icon en la plantilla BindingContext, como se muestra en la Figura 6. El resultado visual se muestra en la Figura 7.

Figura 6 Personalizar la plantilla de elemento para elementos ShellItem en Shell.xaml

<Shell.ItemTemplate>
  <DataTemplate>
    <ContentView HeightRequest="32">
      <ContentView.Padding>
        <Thickness
          Left="32"
          Top="16" />
      </ContentView.Padding>
      <Label Text="{Binding Title}" />
    </ContentView>
  </DataTemplate>
</Shell.ItemTemplate>
<Shell.MenuItemTemplate>
  <DataTemplate>
    <ContentView HeightRequest="32">
      <ContentView.Padding>
        <Thickness
          Left="32"
          Top="16" />
      </ContentView.Padding>
      <Label Text="{Binding Text}" FontAttributes="Bold" />
    </ContentView>
  </DataTemplate>
</Shell.MenuItemTemplate>

Imágenes de resultados de plantilla de elemento de control flotante
Figura 7 Imágenes de resultados de plantilla de elemento de control flotante

Además de personalizar representadores de elementos, vamos a agregar un bonito encabezado al control flotante que incluya un cuadro con una etiqueta y dos botones para un acceso rápido a las características de la cámara. Al igual que con las otras plantillas, agregue uno para FlyoutHeaderTemplate en el archivo Shell.xaml. El contenido puede ser cualquier elemento ContentView, por lo que debe usar un elemento StackLayout para situar verticalmente los controles secundarios, tal como se muestra en el código en la Figura 8. Agregue algunos estilos para acercarse a la composición de diseño y ejecute la aplicación para ver el resultado como se muestra en la Figura 9. Puede establecer FlyoutHeaderBehavior en el elemento del shell para determinar si el encabezado es fijo, o si se puede desplazar o contraer cuando el usuario se desplaza por la pantalla.

Figura 8 FlyoutHeaderTemplate

<Shell.FlyoutHeaderTemplate>
  <DataTemplate>
    <StackLayout HorizontalOptions="Fill" VerticalOptions="Fill"
      BackgroundColor="White" Padding="16">
      <StackLayout.Resources>
        <Style TargetType="Button">
          <Setter Property="BackgroundColor" Value="White" />
          <Setter Property="BorderColor" Value="#2F4B66" />
          <Setter Property="BorderWidth">2</Setter>
          <Setter Property="CornerRadius">28</Setter>
          <Setter Property="HeightRequest">56</Setter>
          <Setter Property="Padding">
            <Thickness
              Left="24"
              Right="24" />
           </Setter>
         </Style>
       </StackLayout.Resources>
       <Label FontSize="Medium" Text="Smart Shopping">
         <Label.Margin>
           <Thickness Left="8" />
         </Label.Margin>
       </Label>
       <Button Image="photo" Text="By taking a photo">
         <Button.Margin>
           <Thickness Top="16" />
         </Button.Margin>
       </Button>
       <Button Image="ia" Text="By using AR">
         <Button.Margin>
           <Thickness Top="8" />
         </Button.Margin>
       </Button>
     </StackLayout>
   </DataTemplate>
 </Shell.FlyoutHeaderTemplate>

Imagen del control flotante con encabezado
Figura 9 Imagen del control flotante con encabezado

Ahora es momento de implementar el comando que se desplaza a las páginas del elemento de menú. Para hacerlo, usaré el nuevo enrutamiento basado en URI que presenta el shell. Los URI permiten a los usuarios saltar al instante a cualquier parte de la aplicación e incluso retroceder sin tener que crear todas las páginas entre los dos puntos. Veamos cómo se consigue.

En primer lugar, necesito declarar las rutas, comenzando con el esquema y el host para mi aplicación, como se indica a continuación:

<Shell
  Route="tailwindtraders"
  RouteHost="www.microsoft.com"
  RouteScheme="app"

Al poner estas piezas juntas en una dirección URL, acabo con el URI siguiente: app://www.microsoft.com/tailwindtraders.

Cada elemento del shell que he definido en el archivo del shell también tiene una propiedad de ruta, que puedo usar más adelante para navegar mediante programación. Para las páginas que no están representadas con un elemento del shell, puedo registrar una ruta explícitamente. Esto es lo que haré para los elementos de menú agregados al control flotante. Cada uno de ellos le remitirá a un elemento ProductCategoryPage, una página que muestra una lista de productos para una categoría específica. Este es el código de registro de ruta:

Routing.RegisterRoute("productcategory", typeof(ProductCategoryPage));

Ahora puedo declarar las rutas necesarias en el constructor de Shell.cs o en cualquier lugar que se ejecute antes de llamar a las rutas. Los elementos de menú exponen un comando para implementar la navegación necesaria, como puede ver en este código:

public ICommand ProductTypeCommand { get; } =
  new Command<string>(NavigateToProductType);
private static void NavigateToProductType(string typeId)
  {
    (App.Current.MainPage as Xamarin.Forms.Shell).GoToAsync(
      $"app:///tailwindtraders/productcategory?id={typeId}", true);
  }

Otra gran ventaja del shell es que tiene métodos de navegación estática que son accesibles desde cualquier parte de la aplicación. Lejos quedan los días de tener que preocuparse por si servicio de navegación estaba disponible pasando de vistas a modelos de vista, y agregando páginas de navegación para encapsularlo todo. Ahora, puede tomar una referencia al shell de la aplicación, que es el elemento MainPage de la aplicación y está accesible como propiedad de App.Current. Puede verlo en el fragmento de código anterior. Para ejecutar la navegación, llame al método GoToAsync y pase una dirección URL válida como elemento ShellNavigationState. Un elemento ShellNavigationState se puede crear a partir de una cadena o un URI. Vuelva a examinar el código y verá que GoToAsync también le permite proporcionar solo una cadena, y que el shell realizará el trabajo para crear una instancia de ShellNavigationState.

Los datos se pueden pasar entre vistas y modelos de vista mediante parámetros querystring. El shell establecerá esos valores directamente en ContentPage o ViewModel al decorar las propiedades adecuadas con atributos de propiedad de consulta, como se muestra en la Figura 10.

Figura 10 Ejemplo de atributo de consulta

[Preserve]
[QueryProperty("TypeID", "id")]
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProductCategoryPage : ContentPage
{
  private string _typeId;
  public ProductCategoryPage()
  {
    InitializeComponent();
    BindingContext = new ProductCategoryViewModel();
  }
  public string TypeID
  {
    get => _typeId;
    set => MyLabel.Text = value;
  }
}

QueryProperty toma el nombre de propiedad pública ("TypeID", en este ejemplo) de la clase receptora y el nombre del parámetro querystring ("id", en este ejemplo) usado en la dirección URL.

Interceptar la acción Atrás

Interceptar la acción Atrás es un requisito común en el desarrollo de aplicaciones móviles, y puede suponer un reto con Xamarin.Forms. El shell soluciona este problema y le permite enlazar con la ruta de navegación antes y después de que se complete para implementar una gran variedad de necesidades personalizadas. Este es un ejemplo de control de navegación, en primer lugar con el código XAML que asigna un controlador de eventos:

<Shell           ...
  Navigating="Shell_Navigating"

Y, a continuación, el código C# para el controlador de eventos:

private void Shell_Navigating(object sender, ShellNavigatingEventArgs e)
{
  if (// Some Boolean evaluation)
  {
    e.Cancel(); // Do not allow this navigation AND/OR do something else
  }
}

En una instancia del shell, agregue un controlador de eventos al evento Navigating. En el código subyacente, ShellNavigatingEventArgs proporciona los detalles básicos de navegación, como se muestra en la Figura 11.

Figura 11 ShellNavigatingEventArgs

Elemento Tipo Descripción
Actuales ShellNavigationState URI de la página actual.
Origen ShellNavigatinState URI que representa dónde se originó la navegación.
Destino ShellNavigationState URI que representa el destino de navegación.
CanCancel Booleanos Propiedad que indica si es posible cancelar la navegación.
Cancelar Booleanos Método para cancelar la navegación solicitada.
Cancelado Booleanos Propiedad que indica si se canceló la navegación actual.

Pestañas, pestañas, pestañas en todas partes

El menú flotante es un patrón de interfaz de usuario popular para la navegación. Cuando piense en la jerarquía del contenido dentro de la aplicación, el nivel superior o más externo de navegación es el menú flotante. Desde allí, el siguiente nivel de detalle es la pestaña de la parte inferior. Si no hay un control flotante presente, las pestañas inferiores se suelen considerar el nivel superior del navegación de una aplicación. A continuación, dentro de las pestañas de la parte inferior, el siguiente nivel de navegación serían las pestañas superiores. Más allá de eso, ya se trata de páginas únicas con vínculos entre ellas. Este es el enfoque subjetivo que el shell adopta para proporcionar la UI de navegación.

Comencemos con las pestañas inferiores. Cada elemento ShellSection de un único elemento ShellItem se puede representar como una pestaña de la parte inferior si hay más de uno. A continuación se incluye un ejemplo de código XAML que produce pestañas inferiores para una aplicación:

<ShellItem Title="Bottom Tab Sample" Style="{StaticResource BaseStyle}">
  <ShellSection Title="AR" Icon="ia.png">
    <ShellContent ContentTemplate="{DataTemplate local:ARPage}"/>
  </ShellSection>
  <ShellSection Title="Photo" Icon="photo.png">
    <ShellContent ContentTemplate="{DataTemplate local:PhotoPage}"/>
  </ShellSection>
</ShellItem>

Este código presenta dos elementos ShellSections en un único elemento ShellItem. Estos elementos ShellSection se representan en la UI como pestañas en la parte inferior de la pantalla. ¿Y qué sucede cuando no necesita el control flotante? Si solo hay un elemento ShellItem, se puede ocultar por completo definiendo FlyoutBehavior como Disabled. Se pueden aplicar estilos a las pestañas con las opciones de estilo existentes o mediante un representador personalizado. A diferencia de los elementos de menú flotante, que pueden ser plantillas de datos personalizadas, las pestañas son más específicas de la plataforma. Para aplicar un estilo al color de las pestañas, use las propiedades de estilo de la clase de shell para los elementos TabBar, como se indica a continuación:

<Style x:Key="BaseStyle" TargetType="Element">
  <Setter Property=
    "Shell.ShellTabBarBackgroundColor"
    Value="#3498DB" />
  <Setter Property=
    "Shell.ShellTabBarTitleColor"
    Value="White" />
  <Setter Property=
    "Shell.ShellTabBarUnselectedColor"
    Value="#B4FFFFFF" />
  </Style>

Al asignar la clase de estilo a ShellItem, los colores se aplican a todas las pestañas de la sección.

Ahora pasemos a las pestañas superiores. Para que se pueda navegar por el contenido desde las pestañas superiores, agregue varios elementos de ShellContent en una única sección ShellSection. El estilo se aplica igual que en el ejemplo anterior para las pestañas inferiores. Este es el código:

<ShellItem Title="Store Home" Shell.TitleView="Store Home"
  Style="{StaticResource BaseStyle}">
    <ShellSection Title="Browse Product">
      <ShellContent Title="Featured"
        ContentTemplate=
        "{DataTemplate local:FeaturedPage}" />
      <ShellContent Title="On Sale"
        ContentTemplate=
        "{DataTemplate local:SalePage}" />
    </ShellSection>
  </ShellItem>

Hoja de ruta

Hay mucho más que descubrir en el shell de Xamarin.Forms. Podría continuar describiendo cómo personalizar la barra de navegación, el botón Atrás y el eficaz controlador de búsqueda que hace que agregar la búsqueda a una página sea más fácil que nunca. Esas características y otras están disponibles ahora y se documentarán a medida que nos acerquemos a una versión estable.

El viaje del shell acaba de empezar. Los desarrolladores de Xamarin.Forms han dejado claro que, a menudo, necesitan que sus aplicaciones para iOS y Android tengan exactamente el mismo aspecto o uno muy similar. Para solucionarlo, tenemos previsto lanzar un shell para Material, que es una implementación del shell que aplica los estilos de Material Design de Google como punto de partida para todos los controles compatibles. Los controles siguen siendo nativos, por lo que no suponen ningún riesgo para el rendimiento ni para las características.

También hay transiciones de navegación y pasos en camino. Las transiciones permiten controlar la animación de una página a otra (izquierda a derecha, derecha a izquierda, encadenada, enrollada, etc.). Los pasos son una forma declarativa de decir "Cuando se produzca esta acción de botón, ejecute esta ruta". Reduce la necesidad de escribir código de navegación GoToAsync y expresa con mayor claridad en XAML cómo se conectan las cosas. La combinación de transiciones y shell de Material puede ofrecer animaciones adicionales, como la animación de elemento principal en que un elemento, como un icono de imagen, hace una transición sencilla de una página a otra.

Empiece a explorar hoy mismo

El shell de Xamarin.Forms está disponible actualmente en la versión preliminar de Xamarin.Forms 4.0, lo que incluye nuevas características increíbles, como CollectionView, CarouselView y los nuevos objetos visuales de Material, que hacen más fácil que nunca empezar las aplicaciones de Xamarin.Forms desde un punto de estilo de UI común y coherente, en lugar del punto en blanco específico de la plataforma. Use el administrador de paquetes de NuGet de Visual Studio para actualizar a la versión 4.0-pre1 activando la opción de versión preliminar.

Para facilitar aún más las cosas, hemos creado un paquete actualizado de plantillas de proyecto que se unifican en el shell y proporcionan la versión 4.0-pre de forma predeterminada. Descargue e instale las plantillas desde aka.ms/xf-shell-templates. Una vez hecho esto, las nuevas plantillas con tecnología del shell estarán disponibles cuando cree un nuevo proyecto de Xamarin.Forms.

A medida que Visual Studio 2019 siga evolucionando, también lo harán Xamarin.Forms 4.0 y el shell. Necesitamos sus comentarios. Para enviarnos sus opiniones y experiencias, visite aka.ms/xf-4-feedback.


David Ortinau es director jefe de programas para herramientas de desarrollo móviles en Microsoft y su trabajo se centra en Xamarin.Forms. Ortinau, desarrollador de .NET desde 2002 y versado en una variedad de lenguajes de programación, ha desarrollado experiencias web, móviles y de entorno para una amplia gama de sectores. Después de varios éxitos con startups tecnológicas y como director de su propia empresa de software, Ortinau se unió a Microsoft para seguir su pasión: crear herramientas que ayudan a los desarrolladores a crear mejores experiencias con las aplicaciones. Cuando no está delante de un equipo o con su familia, está galopando por el bosque.

Gracias a los siguientes expertos técnicos de Microsoft por revisar este artículo: David Britch, Jason Smith


Comente este artículo en el foro de MSDN Magazine