Implementando menús laterales en una app para windows phone

9
This post was published to Desarrollador Windows Phone at 10:13:19 17/01/2014 Implementando Menús Laterales en una App para Windows Phone Antes de empezar quiero compartir con ustedes la siguiente información: El objetivo final de este tutorial es brindarles material que puedan implementar en sus Apps para Windows Phone. Cabe destacar que es idea original de Dan Ardelean y solo lo expreso a mi manera, de tal forma que puedan entenderle un poco mejor. Este artículo es una traducción al español encontrado en el portal developer.nokia, y aquí pueden encontrar la Nota Original A mi manera…. En el artículo Dan comenta que tuvo una charla con su amigo Alessandro Scardova sobre la posibilidad de implementar menús secundarios dentro de una aplicación de Windows Phone (similar a las de la App de Facebook). Incluso si el diseño no es 100% “Modern UI”, pero este cuenta con un buen enfoque para las aplicaciones que tienen múltiples opciones que necesitan ser visitadas de forma rápida (también el enfoque se puede aplicar multiplataforma). Así que previamente pensó en utilizar una plantilla panorama o de pivote, pero después de varias pruebas no fue posible obtener el comportamiento deseado.

Transcript of Implementando menús laterales en una app para windows phone

Page 1: Implementando menús laterales en una app para windows phone

This post was published to Desarrollador Windows Phone at 10:13:19 17/01/2014

Implementando Menús Laterales en una App para Windows Phone

Antes de empezar quiero compartir con ustedes la siguiente información: El objetivo final de este tutorial es brindarles material que puedan implementar en sus Apps para Windows Phone. Cabe destacar que es idea original de Dan Ardelean y solo lo expreso a mi manera, de tal forma que puedan entenderle un poco mejor. Este artículo es una traducción al español encontrado en el portal developer.nokia, y aquí pueden encontrar la Nota Original

A mi manera….

En el artículo Dan comenta que tuvo una charla con su amigo Alessandro Scardova sobre la posibilidad de implementar menús secundarios dentro de una aplicación de Windows Phone (similar a las de la App de Facebook). Incluso si el diseño no es 100% “Modern UI”, pero este cuenta con un buen enfoque para las aplicaciones que tienen múltiples opciones que necesitan ser visitadas de forma rápida (también el enfoque se puede aplicar multiplataforma). Así que previamente pensó en utilizar una plantilla panorama o de pivote, pero después de varias pruebas no fue posible obtener el comportamiento deseado.

Page 2: Implementando menús laterales en una app para windows phone

Objetivos: -Cuando se inicialice la aplicación se deberá visualizar la ventana grafica seleccionada. -Poder deslizarse a la izquierda o derecha para abrir/cerrar los menús secundarios. -Al abrir los menús secundarios, el ApplicationBar no debe de ser visible. -Poder hacer uso de los botones de la parte superior izquierda y derecha para poder abrir los menús secundarios.

NOTA: Los menús laterales tienen una anchura menor de 480, de esta manera cuando se abre todavía se puede visualizar una parte de la ventana principal (incluyendo el botón superior).

La solución que se ha implementado no usa el patrón MVVM, es más una prueba de concepto sobre cómo implementar la funcionalidad. El enfoque es bastante simple, ya que se tiene la visión de que nos movemos dentro de un lienzo a través de manipulaciones y animaciones. Al principio se pensó que solo se podría usar la rejilla sin el lienzo (canvas) y animar el margen de la parrilla, pero como Windows Phone no tiene ThicknessAnimation, las animaciones para abrir y cerrar los menús no eran muy suaves, Dan comenta que también intento implementar el comportamiento swipe utilizando el evento Touch.FrameReported pero los resultados no fueron muy buenos.

Entonces, ¿cómo se puede realizar dicha implementación de los menús? Respuesta rápida: -Se tiene un canvas/grid que tiene un ancho de 1320 y la altura se extiende a toda la altura disponible. -La vista se inserta en un canvas con una posición inicial Canvas.Left , se establece con un valor de -420, de esta manera vemos el menú principal. -Las posiciones fijas dentro del canvas son: 0: Menú de la Izquierda se abrió, -420: Vista Principal y -840: Menú de la Derecha se abrió. -Cuando presionemos los botones nosotros usaremos un recurso Storyboard con un DoubleAnimation para ajustar la posición Canvas.Left dentro del canvas a 0, -420 o -840.

<Canvas.Resources> <Storyboard x:Name="moveAnimation"> <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True" /> </Storyboard> </Canvas.Resources>

Código para que la animación abra o cierre los menús.

void MoveViewWindow(double left) { _viewMoved = true; if (left==-420) ApplicationBar.IsVisible = true; else ApplicationBar.IsVisible = false; ((Storyboard)canvas.Resources["moveAnimation"]).SkipToFill(); ((DoubleAnimation)((Storyboard)canvas.Resources["moveAnimation"]).Children[0]).To = left; ((Storyboard)canvas.Resources["moveAnimation"]).Begin(); }

Page 3: Implementando menús laterales en una app para windows phone

Para implementar el swipe utilizemos el ManipulationStarted, ManipulationDelta y ManipulationEnded en el contenedor del canvas. En Delta fijamos el valor Canvas.Left directamente (sin necesidad de animaciones) entre un máximo de 0 y un mínimo de -840.

private void canvas_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) { if (e.DeltaManipulation.Translation.X != 0) Canvas.SetLeft(LayoutRoot, Math.Min(Math.Max(-840, Canvas.GetLeft(LayoutRoot) + e.DeltaManipulation.Translation.X), 0)); }

Cuando nos deslicemos debemos de memorizar la posición inicial con Canvas.Left. Para esto hacemos la siguiente operación: Si restando el Canvas.Left final y el inicial, el valor absoluto es menor que 100 ( no mucho swipe) nos recuperamos a la posición inicial, de lo contrario nos movemos a la siguiente posición.

private void canvas_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) { var left = Canvas.GetLeft(LayoutRoot); if (_viewMoved) return; if (Math.Abs(initialPosition - left) < 100) { //Regresa a su estado original MoveViewWindow(initialPosition); return; } //Cambio de estado if (initialPosition - left > 0) { //slide a la izquierda if (initialPosition > -420) MoveViewWindow(-420); else MoveViewWindow(-840); } else { //slide a la derecha if (initialPosition< -420) MoveViewWindow(-420); else MoveViewWindow(0); } }

_viewModel se utiliza para ver si la vista ya estaba movida por otro evento desde nuestra manipulación.

Pero veamos mejor el paso a paso. Iniciemos con un nuevo proyecto para que quede más claro:

Page 4: Implementando menús laterales en una app para windows phone

En la parte del XAML de nuestro archivo MainPage.xaml eliminemos todo lo que se encuentra debajo de: shell:SystemTray.IsVisible="True"> hasta </phone:PhoneApplicationPage>

Para que insertemos lo siguiente:

<Canvas x:Name="canvas" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="800" Background="Black" ManipulationStarted="canvas_ManipulationStarted" ManipulationDelta="canvas_ManipulationDelta" ManipulationCompleted="canvas_ManipulationCompleted"> <Canvas.Resources> <Storyboard x:Name="moveAnimation"> <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True" /> </Storyboard> </Canvas.Resources>

<Canvas CacheMode="BitmapCache" x:Name="LayoutRoot" Width="1320" VerticalAlignment="Stretch" Background="Transparent" Canvas.Left="-420" Height="768"> <Border Width="420" CacheMode="BitmapCache" Background="#FF31363E" Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="{Binding ActualHeight, ElementName=canvas}"/> <Border Width="420" Margin="900,0,0,0" CacheMode="BitmapCache" Background="#FF31363E" Grid.Column="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="{Binding ActualHeight, ElementName=canvas}"/>

Page 5: Implementando menús laterales en una app para windows phone

<Grid x:Name="grdCommands" Margin="420,0,0,0" CacheMode="BitmapCache" Grid.Column="1" Background="#FFCFD4E2" Height="{Binding ActualHeight, ElementName=canvas}" Width="480" > <Grid.RowDefinitions> <RowDefinition Height="76"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="#FF3B5998"> <Button Click="OpenClose_Left" Content="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Height="80"/> <Button Click="OpenClose_Right" Content="" HorizontalAlignment="Right" VerticalAlignment="Top" Width="80" Height="80"/> </Grid> <Border Grid.Row="1" Background="#FFCFD4E2"/> </Grid> </Canvas> </Canvas>

Creo y se han de preguntar, ¿Qué acabo de hacer/insertar? Bueno primeramente contamos con un canvas (x:Name=”canvas”)el cual representa la sección principal o el menú de en medio de nuestro proyecto, este contiene un recurso de animación que será el que nos permita hacer los movimientos hacia los lados para mostrar los menús. Después lo que hicimos fue pintar un canvas (x:Name=”LayoutRoot”) con las medidas necesarias para poder mostrar las 3 secciones cuando hagamos el swipe, y en la parte inferior añadimos los menús laterales. También se añadió un Grid que contiene los botones que nos permitirán desplazarnos a los menús laterales en caso de no hacer el swipe. Ya por ultimo un elemento Border para el color de fondo de nuestro Grid principal (x:Name=”grdCommands”).

Así debe de quedar:

Page 6: Implementando menús laterales en una app para windows phone

Ahora pasémonos al código (MainPage.xaml.cs)

Eliminemos todo lo que esta comentado. Y para que nuestro proyecto funcione correctamente deberemos de añadir 2 directivas using: using System.Windows.Media.Animation; using System.Windows.Input;

Después en el componente de inicialización agregaremos lo siguiente: VisualStateManager.GoToState(this, "Normal", false); //Codigo para localizar el ApplicationBar BuildLocalizedApplicationBar();

Después crearemos las acciones de los botones que añadimos con anterioridad en XAML.

private void OpenClose_Left(object sender, RoutedEventArgs e) { var left = Canvas.GetLeft(LayoutRoot); if (left > -100) { ApplicationBar.IsVisible = true; MoveViewWindow(-420); } else { ApplicationBar.IsVisible = false; MoveViewWindow(0); } } private void OpenClose_Right(object sender, RoutedEventArgs e) { var left = Canvas.GetLeft(LayoutRoot); if (left > -520) { ApplicationBar.IsVisible = false; MoveViewWindow(-840); } else { ApplicationBar.IsVisible = true; MoveViewWindow(-420); } }

Después declaramos el método MoreViewWindow que instanciamos con anterioridad para que la animación abra o cierre los menús

void MoveViewWindow(double left) { _viewMoved = true; if (left==-420) ApplicationBar.IsVisible = true; else ApplicationBar.IsVisible = false;

Page 7: Implementando menús laterales en una app para windows phone

((Storyboard)canvas.Resources["moveAnimation"]).SkipToFill(); ((DoubleAnimation)((Storyboard)canvas.Resources["moveAnimation"]).Children[0]).To = left; ((Storyboard)canvas.Resources["moveAnimation"]).Begin(); }

Ahora fijamos el valor directamente (sin necesidad de animaciones) entre un máximo de 0 y un mínimo de -840. private void canvas_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) { if (e.DeltaManipulation.Translation.X != 0) Canvas.SetLeft(LayoutRoot, Math.Min(Math.Max(-840, Canvas.GetLeft(LayoutRoot) + e.DeltaManipulation.Translation.X), 0)); }

El código a continuación expresa lo antes mencionado sobre la memoria inicial del canvas.

double initialPosition; bool _viewMoved = false; private void canvas_ManipulationStarted(object sender, ManipulationStartedEventArgs e) { _viewMoved = false; initialPosition = Canvas.GetLeft(LayoutRoot); } private void canvas_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) { var left = Canvas.GetLeft(LayoutRoot); if (_viewMoved) return; if (Math.Abs(initialPosition - left) < 100) { //Regresa a la posicion original MoveViewWindow(initialPosition); return; } //Cambio de estado if (initialPosition - left > 0) { //Slide a la izquierda if (initialPosition > -420) MoveViewWindow(-420); else MoveViewWindow(-840); } else { //slide a la derecha if (initialPosition < -420) MoveViewWindow(-420); else

Page 8: Implementando menús laterales en una app para windows phone

MoveViewWindow(0); } }

Ya por ultimo agregaremos un método que nos permitirá dibujar y localizar nuestro ApplicationBar

private void BuildLocalizedApplicationBar() { //Establece el ApplicationBar en la página y lo instancia. ApplicationBar = new ApplicationBar(); //Crea un nuevo botón y establecer el valor de texto a la cadena localizada de AppResources. ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/Plus.png", UriKind.Relative)); appBarButton.Text = AppResources.AppBarButtonText; ApplicationBar.Buttons.Add(appBarButton); //Crea un nuevo elemento de menú con la cadena localizada de AppResources. ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarMenuItemText); ApplicationBar.MenuItems.Add(appBarMenuItem); }

Guardemos y compilemos para comprobar que no tengamos ningún error y después ejecutemos nuestra aplicación.

Visualización de nuestro ejemplo:

Page 9: Implementando menús laterales en una app para windows phone

Y como siempre, aquí les comparto el código de este tutorial. Espero y les haya servido.

Happy Coding! P.D Agradezco a Dan Ardelean por su excelente material.