[Windows 10] Novedades para desarrolladores 3 de N

Hola a todos!

Vamos a por la tercera entrega de la serie Windows 10, novedades para desarrolladores. Pero primero, por si te perdiste los anteriores, el índice:

  1. Windows 10, novedades para desarrolladores 3 de N: Nuevos controles

Bonus track: Windows 10 for phones build 10051

Antes de comenzar con el contenido de esta entrega propiamente dicho, una buena noticia. Con la última versión de Windows 10 for phones 10051, ya podemos desplegar aplicaciones desde Visual Studio a nuestro teléfono.

Para ello, primero tendremos que registrar nuestro dispositivo para desarrollo usando la conocida aplicación Windows Phone Developer Registration (10). La diferencia es el número entre paréntesis. Tenemos que asegurarnos de usar la versión 10, no la tradicional 8.1:

image

Solo tienes que presionar el botón “Register” e introducir los datos de tu cuenta LiveID para registrar el nuevo dispositivo.

NOTA: Si antes de actualizar el teléfono a Windows 10, ya lo tenías registrado para desarrollo, no necesitarás volver a registrarlo.

Ahora si, empecemos con la tercera entrega. En esta ocasión, vamos a darle un repaso a nuevos controles incluidos en el SDK.

Entre otras muchas novedades, en este artículo verás dos nuevos controles:

  • RelativePanel, que te ayudará en la creación del Layout de tu página y el soporte a orientaciones y resoluciones diferentes.
  • SplitView, con el que podrás crear los nuevos menús de Windows 10 entre otras cosas.

También veremos nuevas propiedades que se han añadido a los controles contenedores originales (Stack, Grid…) para simplificar nuestro XAML.

RelativePanel

En el anterior artículo de la serie hablamos de como poder adaptar nuestra interfaz de usuario a distintas resoluciones usando Adaptative Visual States. En este sentido, el nuevo RelativePanel nos va a simplificar mucho el trabajo.

El RelativePanel es un control contenedor, al igual que la Grid clásica de XAML, pero que nos permite posicionar los elementos dentro de él de forma relativa al panel y a los elementos contenidos.

Esto nos dá mucha flexibilidad. Por ejemplo empecemos con algo sencillo, dos elementos dentro de un RelativePanel:

<RelativePanel>
    <Rectangle Fill="Purple" Width="250" Height="200"/>
    <Ellipse Fill="Yellow" Width="350" Height="350"/>
</RelativePanel>

Como podemos ver, ambos están posicionados por defecto en el borde superior izquierdo del panel:

image

Ahora, si modificamos nuestro XAML usando las propiedades adjuntas que expone el RelativePanel, podemos obligar al ellipse a situarse en la esquina inferior derecha:

<RelativePanel>
    <Rectangle Fill="Purple" Width="250" Height="200"/>
    <Ellipse Fill="Yellow" Width="350" Height="350"
             RelativePanel.AlignRightWithPanel="True"
             RelativePanel.AlignBottomWithPanel="True"/>
</RelativePanel>

Este XAML, nos ofrece este resultado:

image

Incluso si cambiamos la orientación o la resolución, los elementos se quedarán anclados donde los hemos posicionado. Pero es aún más interesante el poder definir sus posiciones relativas entre ellos, por ejemplo, ahora que hemos posicionado el elipse en la esquina inferior derecha, podemos decirle al rectángulo que se posiciones relativo al elipse:

<RelativePanel>
    <Ellipse x:Name="elipseAmarillo" Fill="Yellow"
             Width="350" Height="350"
             RelativePanel.AlignRightWithPanel="True"
             RelativePanel.AlignBottomWithPanel="True"/>
    <Rectangle Fill="Purple" Width="250" Height="200"
               RelativePanel.AlignTopWith="elipseAmarillo"
               RelativePanel.AlignLeftWith="elipseAmarillo"/>
</RelativePanel>

Esta posición dibujará el siguiente resultado:

image

Lo que hemos echo es alinear los bordes superior e izquierdo de ambos elementos y además alinear los bordes inferior y derecho del elipse con el panel.

Tenemos multitud de opciones más que usar:

  • Below: nos permite indicar que el elemento se alinee debajo del elemento indicado.
  • Above: nos permite indicar que el elemento se alinee encima del elemento indicado.
  • LeftOf/RightOf: posicionar el elemento a la izquierda o derecha del elemento indicado.

De esta forma, toda nuestra interface será relativa y se alineará correctamente independientemente de la resolución o de los cambios de orientación que sufra el dispositivo:

<RelativePanel>
    <Ellipse x:Name="yellowEllipse" Fill="Yellow"
             Width="350" Height="350"
             RelativePanel.AlignRightWithPanel="True"
             RelativePanel.AlignBottomWithPanel="True"/>
    <Rectangle x:Name="purpleRectangle" Fill="Purple"
               Width="250" Height="200"
               RelativePanel.Above="yellowEllipse"
               RelativePanel.AlignLeftWith="yellowEllipse"/>
    <Rectangle Fill="Orange"
               Width="225" Height="300"
               RelativePanel.AlignHorizontalCenterWithPanel="True"
               RelativePanel.LeftOf="purpleRectangle"/>
</RelativePanel>

image

SplitView

Un nuevo chico en el patio de juegos de Windows, pero un antiguo conocido para los que vengan o trabajen con iOS o Android. SplitView es su nombre en Windows, muchos lo conoceréis como el menú hamburguesa… o el menú lateral tan usado en iOS y Android

hamburguer

hamburguersample

El control SplitView es en si mismo toda una revolución en la plataforma Windows, sobre todo en la familia de dispositivos mobile, donde llevamos varios años ya, desde Windows Phone 7, con un patrón de uso en la parte inferior de la pantalla. Ahora de pronto nos vemos cambiando hacia la parte superior… veremos como queda todo finalmente. Pero ahora vamos a ver como funciona este control en Windows 10.

Básicamente, el control Splitview nos permite definir un panel con opciones que puede ser abierto para crear un menú deslizante lateral.

Para empezar, podemos crear un layout como el siguiente:

<Grid Background="LightGray">
    <Grid.RowDefinitions>
        <RowDefinition Height="50"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
        
    <Grid Grid.Row="0" Background="RoyalBlue">
        <ToggleButton x:Name="BurguerToggle"
                      Background="Transparent"
                      IsChecked="False">
                    <FontIcon x:Name="Hamburger"
                           FontFamily="Segoe MDL2 Assets"
                      Foreground="LightCyan"
                      Glyph="" />
        </ToggleButton>
    </Grid>

    <SplitView Grid.Row="1" PanePlacement="Left"
               CompactPaneLength="50"
               OpenPaneLength="320"
               IsPaneOpen="{Binding IsChecked,
                                    ElementName=BurguerToggle}"
               PaneBackground="RoyalBlue"
               DisplayMode="CompactInline">
        <SplitView.Pane>
            <RelativePanel/>
        </SplitView.Pane>
    </SplitView>
</Grid>

En este código, podemos ver como definimos un ToggleButton en la primera Row, que actuará como el botón para abrir y cerrar nuestro SplitView. Usamos un icono de fuente, FontIcon, con la nueva fuente Segoe MDL2 Assets incluida en Windows 10 para definir el símbolo del menú hamburguesa.

A continuación en el SplitView hay ciertas propiedades interesantes:

  • PanePlacement: Donde se situará, el panel desplegable: a izquierda o derecha.
  • DisplayMode: La forma en la que se mostrará el SplitView:
    • CompactInline: compacto, dejando una tira del control visible y en linea con el contenido. Al abrirse, modifica el tamaño del contenido que tenga a su lado.
    • CompactOverlay: compacto, dejando una tira del control visible y sobre el contenido de la pantalla, por lo que no modifica el tamaño de este.
    • Inline: igual que CompactInline, pero sin la tira del control, no se ve nada del SplitView.
    • Overlay: igual que CompactOverlay, pero sin la tira del control, no se ve nada del SplitView.
  • CompactPaneLength: Nos permite definir el ancho de la tira del control cuando está cerrado y el displaymode es CompactInline o CompactOverlay.
  • OpenPaneLength: Nos permite definir el ancho del control abierto.
  • IsPaneOpen: determina si se abre o se cierra el panel. En este caso hemos usado un Binding al ToggleButton para poder hacerlo sin escribir código C#.

El resultado, en Tablet sería este:

image

Y en el teléfono, este otro:

007

En el teléfono no es recomendable dejar un modo Compact, podemos usar AdaptativeVisualStates para cambiar esto dependiendo de la resolución, por ejemplo.

No es un adios, es un hasta luego…

Y con esto termina la tercera entrega de la serie, como siempre, puedes encontrar los ejemplos de este artículo (Win10RelativePanel y Win10SplitView) en mi repositorio de GitHub sobre Windows 10.

Nos vemos pronto!

Un saludo y Happy Coding!

 

[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!