31 Días de Windows 8 | Día 2: Orientación y snapping

Este artículo es una traducción de “Día 2: Orientación y snapping” de Jeff Blakenburg. Puedes encontrar aquí la versión original en inglés.

Hoy vamos a hablar acerca de tamaños de pantalla y porqué ellos son importantes para el desarrollo en Windows 8. En la primera parte de este artículo discutiremos la orientación y algunas maneras simples en las que podemos hacer nuestra aplicación mas útil basados en la forma en que nuestro usuario sostiene su dispositivo.  En la segunda parte, vamos a mirar a nuestra aplicación en un estado “snapped” y como podríamos cambiar nuestra interfaz para acomodarla en un tamaño de pantalla mucho menor.

La orientación y el snap son importantes porque si tu no los consideras en t aplicación, tu aplicación no será aprobada en la Tienda de Windows.

Si miras en los requerimientos de la certificación de aplicaciones de Windows 8, en la sección 3.6 podrás leer.

Tu aplicación debe soportar un diseño acortado. En una orientación horizontal, las funciones de tu aplicación deben ser completamente accesibles cuando el tamaño de la pantalla es de 1024 x 768. Tu aplicación debe permanecer funcional cuando el cliente acorte o agrande la aplicación.

Lo que esto dice es que nuestra aplicación necesita soportar tres estados visuales por lo menos.

  • 1024 x 768 (la resolución mínima y el estado completo)
  • 320 x 768 (snapped)
  • La resolución por defecto para la que estés planeando será generalmente 1366 x 768.

Aquí hay un ejemplo de una aplicación en pantalla completa moviéndose a un tamaño reducido.

A multi-column layout in the unsnapped and snapped states

Puedes ver en este caso, hemos re acomodado nuestro contenido para que pueda caber en un tamaño mas reducido. También hay una oportunidad para mover tu aplicación a un estado “completo” el cual es representado por el bloque gris claro a la derecha de nuestra vista acortada.

Afortunadamente, hay algunas maneras simples de reconocer en que estado se encuentra nuestra aplicación y el resto de este artículo será dedicado a mostrar exactamente como poder hacerlo.

Soportar rotación

Para comenzar vamos a crear nuestra casi famosa aplicación desde la plantilla en blanco de Visual Studio 2012. Una vez que la has creado, corre tu aplicación en el simulador o en una máquina remota ( más de esto adelante). Verás tu asombrosa aplicación blanca y si la rotas, la aplicación estará de hecho rotando también. ¿Por qué? ¿Cómo?

Por defecto, todas las plantillas en Visual Studio están configuradas para soportar todas las rotaciones. Recuerdas el archivo package.appmanifest? En la tabla de la UI de la aplicación encontrarás una sección llamada Orientaciones soportadas (Suported orientations). Al checar una o más de las preferencias estás seleccionando que orientaciones podrá soportar tu aplicación. De nuevo, por defecto las soportará todas.

image_thumb4

Dependiendo de tu situación, este podría ser un valor agregado para la experiencia general de tu aplicación. Por ejemplo, si estás creando un juego quizá solo quieras un modo horizontal.

Reconocer el cambio de orientación

El primer paso al trabajar con orientaciones es asegurarnos que podemos reconocer cuando un cambio de orientación ha sucedido. Afortunadamente, el SDK de Windows 8 nos ha proveído con el sensor SimpleOrientationSensor que tiene eventos para este propósito exacto. Para este ejemplo, hemos comenzado de nuevo con solo una plantilla en blanco en Visual Studio 2012.

Primero, hemos agregado un control simple de TextBox a nuestro archivo MainPage.xaml. Aquí está el conjunto entero de código para este archivo.

<page x:Class="Dia_2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Dia_2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<textblock Text="No orientation reading." x:Name="AlertBox" FontSize="50" TextAlignment="Center" Margin="0,100,0,0" />
</grid>
</page>

Ahora, abre el archivo MainPage.xaml.cs. Necesitamos agregar algo de código para usar este sensor.

Lo primero que agregaremos es una nueva sentencia using: using Windows.Devices.Sensors;. Lo siguiente que agregaremos es una nueva instancia de la clase SimpleOrientationSensor y agregar algunos manejadores de eventos para ser capaces de reconocer el cambio de orientación. Aquí está el código entero de mi archivo MainPage.xaml.cs. Explicaremos el código después. Hay algunas piezas del código C# que debería explicar.

using System;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Sensors;

namespace Dia_2
{
public sealed partial class MainPage : Page
{
private SimpleOrientationSensor sensorOrientacion;

public MainPage()
{
this.InitializeComponent();
sensorOrientacion = SimpleOrientationSensor.GetDefault();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
if(sensorOrientacion != null)
sensorOrientacion.OrientationChanged += sensorOrientacion_OrientationChanged;
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
if(sensorOrientacion != null)
sensorOrientacion.OrientationChanged -= sensorOrientacion_OrientationChanged;
}

async private void sensorOrientacion_OrientationChanged(SimpleOrientationSensor sender, SimpleOrientationSensorOrientationChangedEventArgs args)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
MostrarTextoOrientacion(args.Orientation);
});
}

private void MostrarTextoOrientacion(SimpleOrientation orientacionSimple)
{
switch (orientacionSimple)
{
case SimpleOrientation.Facedown:
txtAlerta.Text = "Hacia abajo";
break;
case SimpleOrientation.Faceup:
txtAlerta.Text = "Hacia arriba";
break;
case SimpleOrientation.NotRotated:
txtAlerta.Text = "Sin rotación";
break;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
txtAlerta.Text = "Rotado 180 grados";
break;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
txtAlerta.Text = "270 grados a la izquierda";
break;
case SimpleOrientation.Rotated90DegreesCounterclockwise:
txtAlerta.Text = "90 grados a la izquierda";
break;
default:
txtAlerta.Text = "Desconocido";
break;
}
}
}
}

Primero, creamos un nuevo objeto SimpleOrientationSensor llamado orientationSensor. En el método constructor, MainPage(), instanciamos el objeto con la orientación preestablecida del sensor del dispositivo.

En el manejador de eventos OnNavigatedTo() y OnNavigatedFrom(), agregamos y retiramos un evento sensorOrientacion_OrientationChanged a nuestro nuevo objeto. Es importante asegurarnos que el objeto no sea nulo porque hay dispositivos que no tienen este sensor obtendrás un error.

Después, tenemos un nuevo manejador de eventos llamado sensorOrientacion_OrientationChanged(). Deberías notar que esta decorado con un descriptor async y utiliza la palabra reservada await cuando ejecuta su acción. Esto es hecho para evitar cuellos de botella en nuestro código que podría de otra manera podría colapsar la aplicación. (Puedes leer un poco más acerca de async/await en MSDN).

Una vez que la información haya sido obtenida, llamamos a un nuevo método, MostrarTextoOrientacion() pasando los datos de la orientación.

Finalmente, MostrarTextoOrientacion() ejecuta un simple ciclo switch con todas las posibiles orientaciones que puedan existir: NotRotated, Rotated90DegreesCounterclockwise, Rotated180DegreesCounterclockwise, Rotated270DegreesCounterclockwise, Facedown, Faceup, ó Unknown. Yo creo que es chistoso que uno haya sido nombrado Rotated180DegreesCounterclockwise dado que a los 180° no importaría desde que dirección haya llegado.

Aquí hay un vistazo rápido de la aplicación en su estado actual.

Depuración remota

Ahora, si no eres como Clark y yo, te gusta entonces escribir tu código en una máquina de escritorio con un procesador de cuatro núcleos, quizá 8-12 GB de RAM, monitor dual de 27’’, mouse y teclado, seleccionar tu monitos para cambiar la orientación simplemente no funcionará. Además del SimpleOrientationSensor, lo que nosotros estamos usando no es una aplicación emulada sino que necesitaremos un dispositivo real para hacerlo.

Otra lección importante que aprendimos: Es un simulador, no un emulador como en Windows Phone. Esto es porque solo simulará la máquina en donde estará corriendo, no como un dispositivo completamente diferente y capaz.

Afortunadamente, Microsoft a dado una forma para que nosotros la podamos utilizar y ver nuestra aplicación en un dispositivo secundario, tal y como lo hacemos al crear aplicaciones Windows Phone. Aquí hay una pequeña historia de como funciona (MSDN tiene la mas larga y completa historia):

Instala las herramientas de depuración remota en el dispositivo secundario. Yo estoy usando una Samsung Series 7 Slate, pero cualquier dispositivo Windows 8 colocado de fábrica en una tableta podría funcionar. Puedes descargar las herramientas de depuración remota desde aquí. Asegúrate de escoger el sabor adecuado entre, x86, x64 o ARM dependiendo de tu dispositivo.

Corre las herramientas remotas en el dispositivo secundario. Verás un ícono se se asemeja a esto:

RemoteDebuggerIcon

Una vez que el depurador remoto esta corriendo en tu dispositivo secundario, regresa a tu máquina primaria y selecciona “Remote Machine” como el objeto para desplegar tu aplicación.

RemoteMachineDebuggingOption

Cuando eligas “Remote Machine” por primera vez, te aparecerá un diálogo que se parece al de la imagen de abajo. Recuerda, los dispositivos en una subred solo aparecerán si las herramientas de depuración remota han sido instaladas y estén ejecutándose.

RemoteDebuggerConnections

 

Después, cuando quieras cambiar dispositivos, vas a molestarte cuando quieras saber donde esta esta opción guardada. Estoy aquí mis queridos lectores para evitarles esa molestia. Abre las propiedades de tu proyecto ( Alt + Enter ) y escoge la tabla de Depuración. Desde aquí, podrás cambiar o remover tu selección previa. Si tu retiras la elección, la próxima vez que escojas la depuración remota, obtendrás el cuadro de diálogo anterior.

ProjectPropertiesDebug

De vuelta al código…

Ok, hasta este punto, tenemos una aplicación que reconoce que la orientación del dispositivo ha cambiado. Todo esto esta bien cuando queremos hacer algo específico “en código” con orientación, pero ¿Qué pasa si nosotros queremos que nuestra aplicación se re oriente a si misma para ser utilizable para nuestro usuario? Hay una manera mucho mas sencilla gracias al VisualStateManager.

Ve de vuelta a tu proyecto y da un clic derecho para abrir el cuadro de diálogo de un nuevo elemento.

AddNewBasicPageDialog

Agrega una nueva página básica, nosotros la nombramos PaginaOrientacion. Si le das un vistazo al XAML para esta página, descubrirás que estamos trabajando con una objeto de página justo afuera de la caja. Esta es una LayoutAwarePage y por defecto ya tiene la suficiente estructura para orientarse a si misma apropiadamente e incluso te da un VisualState para la vista acortada también.

Además, al usar este tipo de página el simulador también respeta los cambios de orientación.

Esto quiere decir que solo por utilizar este tipo de página, automáticamente obtenemos una página lista para la orientación y vista acordada que tiene un conjunto estático de estados visuales que podemos manipular para hacer que nuestra página haga lo que nos gustaría. Para hacer esto mas obvio, voy a modificar mis estados visuales para que cada una tenga un fondo diferente de color.

LandscapeOrientation

PortraitOrientation

SnappedState

Aquí hay un vistazo de los valores modificadoes de nuestra PaginaOrientacion.xaml:

<visualstatemanager .VisualStateGroups>
<visualstategroup x:Name="ApplicationViewStates">
<visualstate x:Name="FullScreenLandscape">
<storyboard>
<objectanimationusingkeyframes Storyboard.TargetName="layoutRoot" Storyboard.TargetProperty="Background">
<discreteobjectkeyframe KeyTime="0" Value="Purple"/>
</objectanimationusingkeyframes>
</storyboard>
</visualstate>
<visualstate x:Name="Filled">
<storyboard>
<objectanimationusingkeyframes Storyboard.TargetName="layoutRoot" Storyboard.TargetProperty="Background">
<discreteobjectkeyframe KeyTime="0" Value="Orange"/>
</objectanimationusingkeyframes>
</storyboard>
</visualstate>
<visualstate x:Name="FullScreenPortrait">
<storyboard>
<objectanimationusingkeyframes Storyboard.TargetName="layoutRoot" Storyboard.TargetProperty="Background">
<discreteobjectkeyframe KeyTime="0" Value="DarkGreen"/>
</objectanimationusingkeyframes>
<objectanimationusingkeyframes Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<discreteobjectkeyframe KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
</objectanimationusingkeyframes>
</storyboard>
</visualstate>
<visualstate x:Name="Snapped">
<storyboard>
<objectanimationusingkeyframes Storyboard.TargetName="layoutRoot" Storyboard.TargetProperty="Background">
<discreteobjectkeyframe KeyTime="0" Value="Blue"/>
</objectanimationusingkeyframes>
<objectanimationusingkeyframes Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<discreteobjectkeyframe KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</objectanimationusingkeyframes>
<objectanimationusingkeyframes Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<discreteobjectkeyframe KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</objectanimationusingkeyframes>
</storyboard>
</visualstate>
</visualstategroup>
</visualstatemanager>

Como puedes ver, simplemente hemos agregado un nuevo nodo para cada sección que modifique la propiedad Background de mi Grid LayoutRoot. Lo que esta nueva LayoutAwarePage nos permite hacer, en lugar de escribir toneladas de código para administrar nuestra orientación, nos  preocupamos por lo que realmente interesa: Nuestra personalización. Al escribir estilos separados para los elementos de nuestra página basados en estados visuales de nuestra página, simplificamos nuestro proceso entero.

En conclusión

Hoy, dimos una vista a como podemos determinar la orientación del dispositivo de un usuario asó como poder utilizar el item LayoutAwarePage para manejar los diferentes estados visuales que nuestra aplicación puede encontrar. Hay toneladas de grandes ejemplos en la web relacionados a orientación y snap, pero hay UNA lección que puedes tomar de este artículo, es:

Tu aplicación DEBE cubrir el estado snapped. Asegúrate de acomodarla.

Para descargar la solución de ejemplo completa de este artículo, puedes descargarla aquí.

downloadXAML

Mañana, vamos a ver el uso de las pantallas de inicio. Es una herramienta valiosa para cargar tu aplicación así como monetizarla. Veremos a fondo esto mañana. ¡Nos vemos!

3 thoughts on “31 Días de Windows 8 | Día 2: Orientación y snapping

  1. Chrsitian

    Gracias por el tutorial!!.Esta nueva teconologia si es muy necesaria aprenderla.
    Hay un pequeno error en:

    No lo reconoce es asi:
    <Textblock Text=…………….
    Solo esa sugerencia para que otras personas no esten perdiendo el tiempo x cosas sencillas
    Otra vez Gracias y hasta pronto

  2. christian

    Al parecer no salio bien mi comentario:
    Solo quisiera corregir……..Eso seria todo

  3. José

    Hola Gracias por compartir tus conocimientos pero hay varias imágenes que ya no están podrías verificar los enlaces por favor para poder visualizar bien los ejemplos Gracias

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">