[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (7 de N)

Hola a todos!

En esta séptima entrada de la serie vamos a revisar dos conceptos indispensables a la hora de crear la experiencia de usuario de una aplicación metro: la barra de aplicación y las orientaciones de la aplicación.

Barra de aplicación

En Windows Phone este componente está limitado por que al no ser un componente nativo de Silverlight, no podemos realizar enlace a datos para usar comandos, aunque existen alternativas que lo implementan, pero que nos exigen usar un componente de terceros para algo tan sencillo como la barra de aplicación.

En WinRT han solventado esto de una forma muy sencilla: la barra de aplicación es un contenedor, donde podremos incluir cualquier botón standard y aprovecharnos de sus capacidades naturales de ejecución de comandos o enlace a datos. Esto nos brinda un gran potencial, pero también implica un peligro: acabar creando “algo” que no es una barra de aplicaciones. Para evitar esto, Microsoft pone a nuestra disposición una guía de estilos muy concreta sobre la App bar.

Guía de Estilo de la barra de aplicación

Lo primero que nos recomienda esta guía es que hagamos un uso consistente de la barra de aplicaciones. Dado que esta se crea por página, no global a toda la aplicación, tenemos que ser especialmente cuidadosos con elementos que estén presentes en varias pantallas, posicionándolos siempre en la misma posición.

Otro punto a tener en cuenta es organizar nuestros comandos en grupos. Si tenemos dos grupos distintos de comandos, como un grupo de creación de contenido (nuevo, guardar, etc…) y uno de ordenación o filtrado, pondremos uno a la derecha y otro alineado a la izquierda. Si tenemos más de dos grupos, pondremos los más parecidos en un lado y los otros en el lado contrario:

image

Además es importante que hagamos esto de forma consistente en toda la aplicación, no podemos cambiar la alineación de los grupos entre pantallas, si decidimos que las opciones de filtrado vayan a la derecha, en todas las pantallas deben aparecer a la derecha.

Barra inferior y… superior

Mientras que en Windows Phone solo existía una barra de aplicación, situada siempre en la parte inferior de la pantalla, en Windows 8 tendremos dos barras de aplicación distintas: la barra inferior y la barra superior. El ejemplo anterior es de una barra inferior, donde ofreceremos opciones al usuario para interactuar con la pantalla que está viendo, sin embargo, en la barra superior ofreceremos opciones de navegación, como ir atrás, ir a otra pantalla o ir a diferentes secciones de la pantalla actual:

image

Para incluir cada una de estas barras, disponemos de dos propiedades dentro de nuestra página TopAppBar y BottomAppBar:

BottomAppBar y TopAppBar
  1. <Page
  2.     x:Class=»win8appbar.BlankPage»
  3.     xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
  4.     xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
  5.     xmlns:local=»using:win8appbar»
  6.     xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″
  7.     xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″
  8.     mc:Ignorable=»d»>
  9.  
  10.     <Grid Background=»{StaticResource ApplicationPageBackgroundThemeBrush}«>
  11.     </Grid>
  12.     
  13.     <Page.BottomAppBar>
  14.         
  15.     </Page.BottomAppBar>
  16.     
  17.     <Page.TopAppBar>
  18.         
  19.     </Page.TopAppBar>
  20. </Page>

Una vez añadidos los tags a nuestro xaml, lo primero que tenemos que hacer es añadir la AppBar:

AppBar
  1. <Page.BottomAppBar>
  2.     <AppBar IsOpen=»True» Opacity=»1″ IsSticky=»True»>
  3.     </AppBar>
  4. </Page.BottomAppBar>
  5.  
  6. <Page.TopAppBar>
  7.     <AppBar IsOpen=»True» Opacity=»1″ IsSticky=»False»>
  8.     </AppBar>
  9. </Page.TopAppBar>

Este elemento tiene dos propiedades muy interesantes, IsOpen, que indica si la AppBar está desplegada o no e IsSticky, que nos indica si cuando el usuario interactúa con la interface la barra debe cerrarse. Por norma general, IsSticky debería ser false, pero puede que deseemos mostrar acciones de la barra de aplicación cuando el usuario ha seleccionado un elemento de la página, incluso cuando selecciona varios. Para estos casos debemos establecer la propiedad IsSticky a true para permitir que el usuario interactúe sin perder de vista la barra de aplicación.

Una vez hecho esto, añadir contenido es tan sencillo como cualquier otro contenedor de XAML:

Contenido AppBar
  1. <Page.BottomAppBar>
  2.     <AppBar IsOpen=»True» Opacity=»1″ IsSticky=»True»>
  3.         <StackPanel Orientation=»Horizontal»>
  4.             <Button BorderBrush=»Transparent» Height=»68″ Margin=»10,0,0,5″>
  5.                 <StackPanel Margin=»-10″>
  6.                     <Viewbox xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»>
  7.                         <Grid Width=»48″ Height=»48″ Visibility=»Visible»>
  8.                             <Rectangle Fill=»#00000000″ Visibility=»Visible» />
  9.                             <Path Data=»M23.916957,4.0498749C24.661973,4.0498755,25.406989,4.6223834,25.971982,5.7673987L29.951907,13.837196C31.081895,16.117462,34.071845,18.29763,36.601836,18.657492L45.501613,19.957292C48.021598,20.317153,48.601668,22.077402,46.771617,23.857181L40.331763,30.137434C38.501712,31.917213,37.351828,35.427454,37.791762,37.947467L39.311759,46.817066C39.741687,49.327308,38.241706,50.417148,35.99174,49.227211L28.02188,45.037284C25.771912,43.857112,22.072013,43.857112,19.812035,45.037284L11.852187,49.227211C9.5922087,50.417148,8.1022395,49.327308,8.5321654,46.817066L10.052163,37.947467C10.482089,35.427454,9.3422125,31.917213,7.5121597,30.137434L1.0723097,23.857181C-0.75774248,22.077402,-0.18768217,20.317153,2.3423117,19.957292L11.242088,18.657492C13.772081,18.29763,16.752021,16.117462,17.882008,13.837196L21.861934,5.7673987C22.426928,4.6223834,23.171943,4.0498755,23.916957,4.0498749z M38.745234,0C39.49026,0,40.235289,0.57005358,40.800307,1.710161L44.780455,9.7809186C45.910495,12.071133,48.900607,14.241336,51.420699,14.611372L60.331027,15.901493C62.851119,16.271527,63.421141,18.031692,61.591071,19.81186L55.150836,26.092449C53.320769,27.872615,52.180728,31.382946,52.610743,33.903183L54.130797,42.764015C54.570815,45.284252,53.070758,46.364353,50.810675,45.184242L42.850383,40.993846C42.460368,40.783828,42.010352,40.633815,41.540336,40.493801L41.300326,39.093669C40.870311,36.583435,42.010352,33.063102,43.840419,31.292938L53.800788,21.582025C55.630854,19.801858,55.060832,18.041693,52.530742,17.671659L38.770232,15.671471C36.240142,15.301436,33.250029,13.131233,32.129989,10.851018L32.089988,10.771011C32.329997,10.450981,32.540004,10.12095,32.710009,9.7809186L36.690158,1.710161C37.255179,0.57005358,38.000205,0,38.745234,0z» Stretch=»Uniform» Fill=»#FFFFFFFF» Width=»30″ Height=»30″ Margin=»0,0,0,0″ />
  10.                         </Grid>
  11.                     </Viewbox>
  12.                     <TextBlock Text=»favorites» HorizontalAlignment=»Center»></TextBlock>
  13.                 </StackPanel>
  14.             </Button>
  15.         </StackPanel>
  16.     </AppBar>
  17. </Page.BottomAppBar>

Tenemos que tener en cuenta que el AppBar solo puede contener directamente un elemento, por esto usamos otros elementos contenedores, como un StackPanel o una Grid para colocar todos nuestros botones.

Orientación de la aplicación

Tras ver la barra de aplicación, otro detalle visual muy importante en las aplicaciones metro es la orientación de la pantalla y como respondemos a ella. Ya no estamos desarrollando para un ordenador portátil o de escritorio solamente, en las aplicaciones metro nos encontraremos en muchos casos, quizás la mayoría, ejecutándonos en tablets de cualquier tipo. La mayoría de estas tablets tendrán  acelerómetros que permitirán al usuario variar la vista del sistema girando el dispositivo. Pasando de una vista horizontal (landscape) o otra vertical (portrait).

En Windows Phone tenemos soporte para estos modos, pero podíamos forzar en nuestra página el modo que deseábamos soportar y olvidarnos del resto. En las aplicaciones metro, tenemos que tener todos los modos presentes, nuestra aplicación debe responder correctamente a los cambios de orientación.

Visual States al rescate

En principio esto parece una tarea complicada, controlar todo el layout de nuestra página y modificarlo dependiendo de la orientación del dispositivo. Pero existe un mecanismo que nos facilitará mucho este trabajo: los Visual States. En Windows Phone o en Silverlight 4, cuando creamos un template para un control, una de las acciones que tenemos a nuestra disposición son los Visual States, que nos permiten cambiar la apariencia de elementos de la template dependiendo de acciones o estados del control como por ejemplo pulsado, deshabilitado, normal, con foco…

Bien, en nuestras aplicaciones metro tendremos un grupo de Visual States que nos indicará el layout en el que se encuentra en cada momento. Este grupo se compone de cuatro estados distintos: FullScreenLandscape, FullScreenPortrait, Filled y Snapped:

Layout VisualStates
  1. <Grid Background=»{StaticResource ApplicationPageBackgroundBrush}«>
  2.     <VisualStateManager.VisualStateGroups>
  3.         <VisualStateGroup>
  4.             <VisualState x:Name=»FullScreenLandscape»>
  5.             </VisualState>
  6.             <VisualState x:Name=»Filled»>
  7.             </VisualState>
  8.             <VisualState x:Name=»FullScreenPortrait»>
  9.             </VisualState>
  10.             <VisualState x:Name=»Snapped»>
  11.             </VisualState>
  12.         </VisualStateGroup>
  13.     </VisualStateManager.VisualStateGroups>
  14. </Grid>

Cada uno representa un posible estado de nuestra pantalla: FullScreenLandscape representa una orientación horizontal del dispositivo y nuestra aplicación a pantalla completa, FullScreenPortrait representa una orientación vertical del dispositivo y nuestra aplicación a pantalla completa, Filled indica una orientación horizontal y nuestra aplicación ocupando la mayor parte de la pantalla y dejando una pequeña parte para otra aplicación y por último Snapped indica nuestra aplicación en esa pequeña parte dejada por una aplicación en modo Filled.

Una vez que hemos llegado a este punto, solo nos queda empezar a trabajar duro en hacer que nuestro layout cambie teniendo en cuenta estos estados. Vamos a empezar por crear un layout simple donde mostremos alguna imágen y texto:

image

Como podéis ver he creado alguna row y column más de las que necesito, esto es para tener una mayor flexibilidad de movimiento al cambiar entre los distintos VisualStates. Por defecto así sería nuestra aplicación, una bonita imagen y un buen texto sacado de Samuel Ipsum. Pero que pasa si cambiamos la orientación, por ejemplo a vertical? Pues que la imagen seguiría en el mismo sitio y el texto, pero al tener menos espacio horizontal se vería todo muy pequeño. Vamos a animar los estados de la página, abriendo la pestaña States de Expression Blend y seleccionando FullScreenPortrait, también, para tener más referencias visuales podemos ir a la pestaña de plataforma y cambiar la orientación a Portrait. Lo que voy a hacer es cambiar las columns y rows a las que está añadido cada elemento para aprovechar mejor el espacio en vertical:

image

Y que se ha generado por debajo en nuestro XAML? Muchas animaciones:

FullScreenPortrait
  1. <VisualState x:NameFullScreenPortrait«>
  2.     <Storyboard>
  3.         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty(Grid.RowSpan)« Storyboard.TargetNameimage«>
  4.             <DiscreteObjectKeyFrame KeyTime0«>
  5.                 <DiscreteObjectKeyFrame.Value>
  6.                     <x:Int32>2</x:Int32>
  7.                 </DiscreteObjectKeyFrame.Value>
  8.             </DiscreteObjectKeyFrame>
  9.         </ObjectAnimationUsingKeyFrames>
  10.         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty(Grid.ColumnSpan)« Storyboard.TargetNameimage«>
  11.             <DiscreteObjectKeyFrame KeyTime0«>
  12.                 <DiscreteObjectKeyFrame.Value>
  13.                     <x:Int32>3</x:Int32>
  14.                 </DiscreteObjectKeyFrame.Value>
  15.             </DiscreteObjectKeyFrame>
  16.         </ObjectAnimationUsingKeyFrames>
  17.         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty(Grid.Row)« Storyboard.TargetNametextBlock«>
  18.             <DiscreteObjectKeyFrame KeyTime0«>
  19.                 <DiscreteObjectKeyFrame.Value>
  20.                     <x:Int32>2</x:Int32>
  21.                 </DiscreteObjectKeyFrame.Value>
  22.             </DiscreteObjectKeyFrame>
  23.         </ObjectAnimationUsingKeyFrames>
  24.         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty(Grid.Column)« Storyboard.TargetNametextBlock«>
  25.             <DiscreteObjectKeyFrame KeyTime0«>
  26.                 <DiscreteObjectKeyFrame.Value>
  27.                     <x:Int32>0</x:Int32>
  28.                 </DiscreteObjectKeyFrame.Value>
  29.             </DiscreteObjectKeyFrame>
  30.         </ObjectAnimationUsingKeyFrames>
  31.         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty(Grid.ColumnSpan)« Storyboard.TargetNametextBlock«>
  32.             <DiscreteObjectKeyFrame KeyTime0«>
  33.                 <DiscreteObjectKeyFrame.Value>
  34.                     <x:Int32>3</x:Int32>
  35.                 </DiscreteObjectKeyFrame.Value>
  36.             </DiscreteObjectKeyFrame>
  37.         </ObjectAnimationUsingKeyFrames>
  38.         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty(FrameworkElement.Margin)« Storyboard.TargetNametextBlock«>
  39.             <DiscreteObjectKeyFrame KeyTime0«>
  40.                 <DiscreteObjectKeyFrame.Value>
  41.                     <Thickness>50,-20,50,50</Thickness>
  42.                 </DiscreteObjectKeyFrame.Value>
  43.             </DiscreteObjectKeyFrame>
  44.         </ObjectAnimationUsingKeyFrames>
  45.     </Storyboard>
  46. </VisualState>

Simplemente hemos tomado el trabajo de planificar antes de comenzar a diseñar que podríamos necesitar para colocar nuestra información y a continuación hemos realizado los cambios necesarios con Blend para que se adapte nuestra aplicación a la resolución, el resultado? Al ejecutar nuestra aplicación no funcionan las animaciones que hemos creado, no cambia el estado… Esto es porque necesitamos indicarle a nuestra página a que estado debe ir cuando la orientación o posición cambien, simplemente en el código de nuestra página, usando el namespace Windows.UI.ViewManagement obtendremos el ApplicationView que nos devolverá en todo momento el ViewState en el que nos encontremos. Lo único que necesitamos es subscribirnos al evento SizeChanged de nuestra ventana y usar el método GoToState del VisualStateManager:

Ahora sí, si ejecutamos veremos como nuestra aplicación reacciona a las diferentes orientaciones y estados:

image

Conclusión

En este séptima entrega de la serie hemos podido ver dos de las novedades en el apartado de layout que nos ofrece metro en comparación con Windows Phone, simplemente teniéndolas en cuenta, mejoraremos la experiencia de usuario de nuestra aplicación en gran medida y por fin hemos empezado a ver algo más que Visual Studio, a utilizar el nuevo Expression Blend. Como siempre, aquí os dejo los ejemplos del artículo para que podáis jugar con ellos y tenerlos como referencia. Nos vemos en el siguiente artículo!

Un saludo y Happy Coding!

Cambiando el VisualState
  1. public BlankPage()
  2. {
  3.     this.InitializeComponent();
  4.  
  5.     Window.Current.SizeChanged += Current_SizeChanged;
  6.     VisualStateManager.GoToState(this, ApplicationView.Value.ToString(), true);
  7. }
  8.  
  9. void Current_SizeChanged(Object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
  10. {
  11.     VisualStateManager.GoToState(this, ApplicationView.Value.ToString(), true);
  12. }

Un comentario sobre “[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (7 de N)”

Deja un comentario

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