[Windows 10] Novedades para desarrolladores 2 de N

Hola a todos!

Seguimos con el segundo artículo de la serie sobre novedades para desarrolladores en Windows 10. Aquí tienes el índice de artículos:

  1. Windows 10, novedades para desarrolladores 2 de N: UI Adaptativa

En esta ocasión vamos a hablar de los nuevos adaptative visual states y sobre como adaptar nuestra interfaz de usuario a las diferentes familias de dispositivos existentes.

En las aplicaciones universales para Windows 8.1 y Windows Phone 8.1, teníamos un proyecto diferente para cada plataforma. Esto facilitaba el crear una interfaz de usuario adaptada, simplemente creando la misma página dos veces, una por cada plataforma.

Sin embargo, en Windows 10 solo disponemos de un proyecto, ¿Como podemos adaptar nuestra interfaz de usuario?

Existen dos formas principalmente: Podemos crear varias vistas XAML para una misma página o podemos modificar el aspecto de nuestro XAML mediante visual states.

Adaptative visual states

Si ya has desarrollado en XAML para Windows o Windows Phone, te sonarán los Visual States

Éstos “estados visuales” te permiten definir grupos de cambios de la interfaz de usuario dentro de tu XAML, para una página o un control, que definan diferentes estados. Por ejemplo, podíamos definir un estado para indicar que estamos cargando datos, otro estado para cuando el usuario haga un gesto predeterminado (un swipe, un fick…)

Lo único que les faltaba era una forma sencilla de usar Visual States para el cambio de nuestra interfaz de usuario dependiendo de la resolución vertical/horizontal del dispositivo donde se ejecutaba la app. Este es el hueco que cubren precisamente los Adaptative Visual States. Mediante el uso de un nuevo tipo de trigger, el AdaptativeTrigger, puedes crear VisualStates que se ejecuten automáticamente basándose en el tamaño de la ventana de la aplicación.

Pongamos como ejemplo el siguiente XAML que hemos creado en un proyecto Blank application (UAP) para Windows 10:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Border Margin="24,24,0,12" BorderBrush="Red" BorderThickness="2" Background="LightCyan">
        <TextBlock x:Name="TitleText" FontSize="48" Text="This is a long text title!" Foreground="Black"/>
    </Border>
    <StackPanel x:Name="ListPanel" Orientation="Vertical">
        <Image x:Name="Image01" Source="/Assets/Bilbao001.jpg" MaxHeight="120" Stretch="UniformToFill"/>
        <Image x:Name="Image02" Source="/Assets/Bilbao002.jpg" MaxHeight="120" Stretch="UniformToFill"/>
        <Image x:Name="Image03" Source="/Assets/Bilbao003.jpg" MaxHeight="120" Stretch="UniformToFill"/>
    </StackPanel>
</StackPanel>

Si ejecutamos la aplicación en el emulador de Windows 10 mobile y en Windows 10 obtendremos el siguiente resultado:

image

El resultado no es bueno en ninguna de las dos plataformas. En Tablet/Desktop vemos todo el título, pero las imágenes se estiran demasiado y la altura máxima que les hemos puesto hacen que no se vean bien. En el emulador del teléfono, las imágenes se ven bien, pero el título es demasiado grande y no se ve entero.

Vamos a crear un primer Visual State que ajuste el texto del título para que se vea correctamente en el teléfono:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
        <VisualState x:Name="NarrowState">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="300"/>
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="TitleText.FontSize"
                        Value="24"/>
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Con el AdaptativeTrigger le indicamos al sistema que lance los Setters cuando la resolución de pantalla horizontal sea igual o mayor al tamaño mínimo indicado. En este caso cambiamos el tamaño de fuente del título a uno más adecuado. Ahora podemos crear otro Visual State que controle una resolución mayor, para adaptar el contenido a Tablets/Desktops:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
        <VisualState x:Name="NarrowState">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="300"/>
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="TitleText.FontSize"
                        Value="24"/>
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="WideState">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="600"/>
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="ListPanel.Orientation"
                        Value="Horizontal"/>
                <Setter Target="Image01.MaxHeight"
                        Value="600"/>
                <Setter Target="Image02.MaxHeight"
                        Value="600"/>
                <Setter Target="Image03.MaxHeight"
                        Value="600"/>
                <Setter Target="Image01.MaxWidth"
                        Value="300"/>
                <Setter Target="Image02.MaxWidth"
                        Value="300"/>
                <Setter Target="Image03.MaxWidth"
                        Value="300"/>
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

En este caso, cuando la resolución es mayor de 600 píxeles, cambiamos la orientación del StackPanel y los tamaños máximos de las imágenes, para aprovechar mejor la pantalla. Todo, usando como disparador el AdaptativeTrigger. ¿El resultado? Aquí podéis ver algunos ejemplos:

image

Esto ya tiene otro aspecto… ahora nuestras imágenes y textos se adaptan al tamaño de su contenedor para ofrecer la mejor experiencia en cada momento.

Es importante tener algo en cuenta. Con los Adaptative Visual States, estamos trabajando con resoluciones, no con plataformas. Por eso en la imagen superior, podemos ver tanto en Tablet como en Phone, el mismo layout, dependiendo solo de la resolución horizontal en cada momento.

¿Y si quiero una vista específica para dispositivos móviles, por ejemplo? Esto no te sirve. Ten en cuenta que puedes tener smartphones con una resolución horizontal de 400 píxeles y otros con 1080 píxeles… y si los pones en modo landscape, hasta 1920 píxeles. Lo mismo que una pantalla de PC y muchas tablets del mercado.

Si quieres tener una vista en especial para una familia de dispositivos, sigue leyendo en el siguiente apartado.

Device family views

Puede que en ocasiones tu interfaz de usuario sea tan compleja, que adaptarla mediante los Visual States sea una locura. O simplemente que los cambios sean tantos, que casi merecería la pena crear una pantalla nueva desde cero.

Para estos casos, Microsoft ha añadido al SDK de Windows 10 el concepto de “Device family views”, que nos permite añadir múltiples vistas .xaml a una misma página, identificando cada una por convención.

Vamos a empezar por crear un nuevo proyecto Blank Application (UAP) que llamaremos WIn10DeviceFamilyViews.

En la página principal MainPage, vamos a crear la interfaz de usuario por defecto para Tablet/Desktop, sin usar Adaptative Visual States:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Border Margin="24" BorderBrush="Red" BorderThickness="2"
            Background="LightCyan">
        <TextBlock x:Name="TitleText" FontSize="48"
                    Text="This is the default view for mainpage"
                    Foreground="Black"/>
    </Border>
    <StackPanel Margin="24" x:Name="ListPanel" Orientation="Horizontal">
        <Image x:Name="Image01" Source="/Assets/Bilbao001.jpg"
                MaxHeight="600" MaxWidth="300" Stretch="UniformToFill"/>
        <Image x:Name="Image02" Source="/Assets/Bilbao002.jpg"
                MaxHeight="600" MaxWidth="300" Stretch="UniformToFill"/>
        <Image x:Name="Image03" Source="/Assets/Bilbao003.jpg"
                MaxHeight="600" MaxWidth="300" Stretch="UniformToFill"/>
    </StackPanel>
</StackPanel>

El resultado:

image

Ahora, vamos a crear una vista específica para la familia de dispositivos mobile.

En primer lugar, vamos a añadir una nueva carpeta a nuestro proyecto llamada “DeviceFamily-Mobile”. Por convención, cuando la familia de dispositivos en la que nos ejecutemos sea mobile y esta carpeta exista, se buscará por cada página si existe una vista xaml en ella. Si existe, se usará en lugar del xaml por defecto.

Una vez creada la carpeta, vamos a añadir un nuevo item, pero no añadiremos una página nueva, en su lugar seleccionaremos el item Xaml View de la ventana de añadir nuevo item. Lo llamaremos igual que la página a la que deseamos añadirla. En este caso MainPage.xaml:

image

Una vez añadida nos daremos cuenta de que no tiene archivo cs asociado. Pero si hacemos click en la ventana de XAML y seleccionamos view code (F7) nos abre un archivo de code behind… es el de la página principal.

Ahora podemos empezar a diseñar nuestra vista mobile. Le añadimos este XAML:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Border Margin="24,24,24,12" BorderBrush="Red" BorderThickness="2"
            Background="LightCyan">
        <TextBlock x:Name="TitleText" FontSize="26"
                    Text="This is the mobile view for mainpage"
                    Foreground="Black"/>
    </Border>
    <StackPanel Margin="24,0,24,24" x:Name="ListPanel" Orientation="Vertical">
        <Image x:Name="Image01" Source="/Assets/Bilbao001.jpg"
                MaxHeight="230" Stretch="UniformToFill"/>
        <Image x:Name="Image02" Source="/Assets/Bilbao002.jpg"
                MaxHeight="230" Stretch="UniformToFill"/>
        <Image x:Name="Image03" Source="/Assets/Bilbao003.jpg"
                MaxHeight="230" Stretch="UniformToFill"/>
    </StackPanel>
</StackPanel>

Es muy parecido al XAML que teníamos en la página principal, pero totalmente adaptado al uso vertical y menor resolución.  Incluso podemos añadir nuevos elementos no necesarios en la vista por defecto, como un scroll para ver las imágenes más grandes.

Si ahora volvemos a ejecutar la aplicación tanto en Tablet como en el emulador del teléfono, veremos que en el primer caso sigue usando la vista por defecto mientras que en el segundo hace uso de nuestra nueva vista xaml:

image

Cada familia de dispositivos tiene sus vistas independientes, lo que nos aporta la misma flexibilidad que teníamos en los proyectos universales de 8.1, pero con la nueva estructura unificada. Además podemos mezclar ambas técnicas: Adaptative visual states y Vistas por familia de dispositivo, según sea necesario en cada página.

Esto ha sido todo amigos…

Por ahora!! Espero que os guste el artículo y os sea útil el código, que como siempre, tenéis en el repo de GitHub de Windows 10 que he creado.

Volveremos a vernos en breve con más cosas interesantes sobre las novedades de Windows 10 para desarrolladores.

Un saludo y Happy Coding!

 

3 comentarios en “[Windows 10] Novedades para desarrolladores 2 de N”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *