Advertisement
  1. Code
  2. Windows

Cómo crear tu primera aplicación de Windows Universal

Scroll to top
Read Time: 13 min

() translation by (you can also view the original English article)

Las aplicaciones de Windows Universal te permiten programar para todos los dispositivos Windows con una solución. Desarrollas una vez, compartes la mayor parte de tu código y despliegas el resultado en Windows, Windows Phone o Xbox. 

El objetivo es maximizar la reutilización de código. Puedes compartir código, usar controles, estilos, cadenas y otros recursos entre los proyectos de Windows Phone y Windows 8 en Visual Studio. Esto reduce el esfuerzo necesario para construir y dar mantenimiento a una aplicación para cada tipo de dispositivo.

Introducción

Desde el punto de vista de un desarrollador, una aplicación de Windows Universal no es un único binario que se ejecuta en múltiples plataformas. En vez de eso, la aplicación toma la forma de una solución de Visual Studio que contiene múltiples proyectos, uno por cada plataforma específica, además de un proyecto compartido que contiene código y recursos compartidos entre plataformas. Es posible compartir una buena parte del código entre los proyectos, ya que Windows Phone 8.1 implementa la mayoría de las APIs de WinRT que Windows 8.1 implementa.

Puedes crear una aplicación de Windows Phone usando el motor en tiempo de ejecución de Silverlight (versión 8.0 u 8.1) o el motor en tiempo de ejecución de WinRT (el de las aplicaciones de Windows Universal). El motor en tiempo de ejecución de WinRT te permite crear una aplicación que podrá ejecutarse en Windows, Windows Phone e incluso Xbox One.

Estamos usando el framework XAML para desarrollar una aplicación para múltiples plataformas. En la versión actual hay una convergencia de APIs del 90%, pero todavía hay un pequeño conjunto que no ha convergido. Las funciones de Windows Phone que solamente están disponibles en el framework Silverlight son:

  • Soporte para lentes
  • Soporte para VoIP
  • Tarea de captura de cámara
  • APIs del portapapeles
  • API para fondos de bloqueo de pantalla

En este tutorial usaré una plantilla para aplicaciones de Windows Universal para crear una aplicación Hex Clock, que es un reloj hexadecimal preciso a color. Este recorre todo el rango de colores de las 24 horas, desde el color #000000 hasta el #235959. El fondo de la aplicación cambia según el color que le corresponda a la hora actual convertida a hexadecimal con cada tic del reloj. Esta usa la misma implementación que el Reloj de Color Hexadecimal en JS para generar el código hexadecimal de la hora actual.

El diseño está inspirado en un tutorial para crear una aplicación de reloj en Windows Phone 7 de Tuts+. Si bien la aplicación de reloj solamente está dirigida a Windows Phone, vamos a usar su diseño para crear una aplicación similar para Windows Phone 8.1 y para Windows 8.1. La siguiente captura de pantalla muestra lo que vamos a construir.

Final image of how hexadecimal clock will lookFinal image of how hexadecimal clock will lookFinal image of how hexadecimal clock will look

En este tutorial discutiré los siguientes temas, que son relevantes para desarrollar aplicaciones de Windows Universal:

  • La estructura de las aplicaciones de Windows Universal
  • Cómo cambiar entre proyectos de inicio en Visual Studio
  • El selector de contexto para aplicaciones de Windows Universal en el editor de Visual Studio
  • Cómo escribir código multiplataforma en el proyecto compartido
  • Cómo añadir soporte para Windows o Windows Phone en un proyecto existente
  • Cómo construir una aplicación de Windows Universal desde cero

1. La estructura de las aplicaciones de Windows Universal

Una aplicación de Windows Universal es una colección de tres proyectos incluidos en una carpeta de solución opcional. Los proyectos de Windows y Windows Phone son proyectos de plataforma y son responsables de la creación de paquetes de aplicación (.appx), que se enfocan en sus plataformas correspondientes. Estos proyectos contienen recursos específicos de la plataforma que quiera abordarse.

El proyecto compartido es un contenedor para el código que se ejecuta en ambas plataformas. Estos proyectos no tienen una salida binaria, pero sus contenidos son importados por los proyectos de plataforma y usados como parte del proceso de compilación para generar los paquetes de aplicación (.appx).

La siguiente captura de pantalla muestra la solución que Visual Studio crea cuando eliges la plantilla de proyecto para una aplicación en blanco o Blank App (Universal Apps).

Universal app solution structureUniversal app solution structureUniversal app solution structure

Visual Studio 2013 Actualización 2 introduce la nueva característica que son las aplicaciones para Windows Universal. Descarga e instala esta actualización antes de que comiences a crear aplicaciones de Windows Universal.

2. Cómo cambiar entre proyectos de inicio

Cuando ejecutas la solución, el proyecto que se ejecuta es aquel que está seleccionado como proyecto de inicio. Para establecer el proyecto de inicio, haz clic con el botón derecho en el nodo del proyecto dentro del Solution Explorer (Explorador de Soluciones) y elige la opción Set as Startup Project (Establecer como Proyecto de Inicio). Puedes cambiar rápidamente el proyecto de inicio desde el menú desplegable Debug target (Destino de depuración) que ahora enumera todos los proyectos posibles en la solución.

Switching startup projectsSwitching startup projectsSwitching startup projects

El proyecto que elijas aparecerá en negritas en el Solution Explorer (Explorador de Soluciones). Los destinos de depuración que se encuentran disponibles cambian al seleccionar diferentes proyectos de inicio.

  • Cuando el proyecto Windows es el proyecto de inicio, el menú desplegable Debug target (Destino de depuración) muestra las opciones Simulator (Simulador) de Windows o Local Machine (Equipo local).
  • Cuando el proyecto de Windows Phone es el proyecto de inicio, el menú desplegable muestra la opción Device (Dispositivo) así como diferentes emuladores.

3. El selector de contexto en el editor de código

Al escribir código en un proyecto compartido puedes usar el selector de contexto del proyecto en la barra de navegación para elegir la plataforma que estés abordando activamente, lo que a su vez personaliza la experiencia con IntelliSense en el editor de código.

Context switcher in the editorContext switcher in the editorContext switcher in the editor

Si usas una API en el código compartido que no sea compatible con ambas plataformas, un mensaje de error identificará dicha API cuando compiles el proyecto. No tienes que compilar el proyecto para confirmar que estés usando APIs multiplataforma.

La siguiente captura de pantalla muestra un ejemplo de los iconos de advertencia e IntelliSense para un tipo que es compatible solamente con las aplicaciones de Windows Phone.

Example of warning icons and IntellisenseExample of warning icons and IntellisenseExample of warning icons and Intellisense

4. Código multiplataforma en el proyecto compartido

En el proyecto compartido generalmente escribes código común para ambas plataformas. Para aislar secciones de código específicas de cada plataforma, usa la directiva #ifdef. Las constantes WINDOWS_APP y WINDOWS_PHONE_APP han sido predefinidas para ti.

Las siguientes son las constantes de compilación condicional que puedes usar para escribir código específico para cada plataforma:

C# WINDOWS_APP
WINDOWS_PHONE_APP
C++
WINAPI_FAMILY_PC_APP
WINAPI_FAMILY_PHONE_APP

Cuando escribes código en el proyecto compartido, el editor de código de Visual Studio usa un contexto que se enfoca en una plataforma o en la otra. En C#, el IntelliSense que ves al escribir código es específico del contexto del editor de código, es decir, es específico de Windows o de Windows Phone.

5. Cómo añadir soporte para Windows/Windows Phone

Si ya tienes una aplicación de Windows 8.1 existente, puedes usar el comando Add Windows Phone 8.1 (Añadir Windows Phone 8.1) para agregar un nuevo proyecto de Windows Phone 8.1 y un proyecto compartido a la solución. También hay una opción similar disponible si tienes una aplicación de Windows Phone 8.1 y quieres añadir soporte para Windows 8.1.

Para agregar soporte para un tipo de dispositivo u otro, en el Solution Explorer (Explorador de Soluciones) haz clic con el botón derecho en el proyecto y elige Add Windows Phone 8.1 (Añadir Windows Phone 8.1) o Add Windows 8.1 (Añadir Windows 8.1).

Add Windows 81 app to existing Windows Phone 81 projectAdd Windows 81 app to existing Windows Phone 81 projectAdd Windows 81 app to existing Windows Phone 81 project

Aquí Visual Studio agrega un nuevo proyecto Windows Phone o Windows a la solución. Además se crea un proyecto compartido automáticamente.

La siguiente captura de pantalla muestra una solución después de añadir un proyecto de Windows Phone a un proyecto de Windows existente. El proyecto compartido que es añadido a la solución inicialmente está vacío.

Project structure after adding a Windows 81 project to an existing Windows Phone 81 appProject structure after adding a Windows 81 project to an existing Windows Phone 81 appProject structure after adding a Windows 81 project to an existing Windows Phone 81 app

Toma en cuenta que, si creas una aplicación usando una plantilla para aplicaciones de Windows Universal, el proyecto compartido ya contendrá el archivo App.xaml.

Paso 1: Mover los archivos al proyecto compartido

Puedes mover el código que quieras compartir entre aplicaciones al proyecto compartido. Por ejemplo, puedes mover las carpetas Common, DataModel y Strings a dicho proyecto. Incluso puedes mover App.xaml al proyecto compartido.

Sin embargo es posible que veas algunos errores de compilación relacionados con el código que muevas al proyecto compartido. Puedes resolver estos errores configurando tu nuevo proyecto de aplicación para que tenga el mismo conjunto de referencias que tienes en tu proyecto inicial.

La siguiente captura de pantalla muestra la misma referencia a un ensamblado añadida a ambos proyectos.

Adding same assembly reference to both projectsAdding same assembly reference to both projectsAdding same assembly reference to both projects

Si tu proyecto compartido usa APIs específicas de Windows, usa la directiva #ifdef con la constante WINDOWS_APP para aislar esa sección de código. Usa la constante WINDOWS_PHONE_APP para aislar secciones de código específico de Windows Phone 8.1.

Paso 2: Compartir App.xaml

Cuando creas una nueva solución para una aplicación de Windows Universal, Visual Studio coloca el archivo App.xaml en el proyecto compartido. Si conviertes un proyecto existente a una aplicación de Windows Universal puedes mover App.xaml manualmente al proyecto compartido. Debes configurar la propiedad de acción de compilación de la página con el valor ApplicationDefinition (Definición de la aplicación) después de mover el archivo. Estos son los pasos a seguir:

  • Dentro del Solution Explorer (Explorador de Soluciones), en el proyecto compartido, selecciona el archivo App.xaml.
  • Selecciona la ventana View > Properties (Vista > Propiedades).
  • En la ventana Properties (Propiedades), dentro de la lista desplegable Build Action (Acción de compilación), selecciona ApplicationDefinition (Definición de la aplicación).

También debes decidir cómo quieres abrir la primera página de tu aplicación. Si compartes el archivo App.xaml y quieres usar una página de inicio diferente para cada aplicación, tienes que añadir directivas #ifdef como se muestra a continuación.

1
#if WINDOWS_APP

2
if (!rootFrame.Navigate(typeof(HubPage)))
3
#endif

4
#if WINDOWS_PHONE_APP

5
if (!rootFrame.Navigate(typeof(WindowsPhoneStartPage)))
6
#endif

7
{
8
    throw new Exception("Failed to create initial page");
9
}

6. Comienza a escribir una aplicación de Windows Universal

Paso 1: Configuración del proyecto

En primer lugar, elige una plantilla de proyecto para una aplicación de Windows Universal en el cuadro de diálogo New Project (Nuevo proyecto). La siguiente captura de pantalla muestra las plantillas de proyecto para aplicaciones de Windows Universal que están disponibles actualmente para C#.

Universal Windows app templatesUniversal Windows app templatesUniversal Windows app templates

Asigna un nombre al proyecto. Voy a usar el nombre Hex Clock Pro para mi proyecto.

Paso 2: Construir la interfaz de usuario

En su mayoría, el trabajo relacionado con la interfaz de usuario se lleva a cabo en los proyectos específicos de plataforma, lo que te permite crear una interfaz de usuario que se ve muy bien en computadoras, tabletas y teléfonos, pero que comparte datos, recursos, componentes e incluso vistas-modelos en común.

En vez de construir interfaces de usuario separadas para las versiones de Hex Clock Pro en Windows Phone 8.1 y Windows 8.1, he definido un diseño común en el proyecto compartido. Solamente tengo que hacer algunos cambios en el XAML de la aplicación de reloj en Tuts+ para que funcione en ambas plataformas.

1
<Canvas x:Name="ContentPanel" Margin="12,0,620,0" HorizontalAlignment="Center" Grid.Row="1" RenderTransformOrigin="0.5,0.5">
2
    <Canvas.RenderTransform>
3
        <CompositeTransform Rotation="-30"/>
4
    </Canvas.RenderTransform>
5
    <Canvas x:Name="TimeText" Height="315" Canvas.Left="-18" Canvas.Top="288" Width="496" RenderTransformOrigin="0.5,0.5" Opacity="0">
6
        <Canvas.RenderTransform>
7
            <CompositeTransform/>
8
        </Canvas.RenderTransform>
9
        <TextBlock x:Name="TimeHours" TextWrapping="Wrap" Text="12" Canvas.Top="24" Style="{StaticResource TimeTextStyle}" Canvas.Left="-67" Width="267" TextAlignment="Right"/>
10
        <TextBlock x:Name="TimeDots" Canvas.Left="204" TextWrapping="Wrap" Text=":" Style="{StaticResource TimeTextStyle}"/>
11
        <TextBlock x:Name="TimeMinutes" Canvas.Left="263" TextWrapping="Wrap" Text="59" Canvas.Top="24" Style="{StaticResource TimeTextStyle}" Width="257"/>
12
    </Canvas>
13
    <Rectangle x:Name="HorizontalSeparator" Height="4" Canvas.Left="-400" Canvas.Top="295" Width="1020" Fill="White"/>
14
    <Rectangle x:Name="VerticalSeparator" Fill="White" Height="469" Canvas.Left="213" Canvas.Top="489" Width="4"/>
15
    <TextBlock x:Name="ApplicationTitle" TextWrapping="Wrap" Text="HEX CLOCK PRO" Canvas.Top="271" Foreground="White" FontSize="16" Canvas.Left="18"/>
16
    <TextBlock x:Name="SecondsLabel" Height="36" Canvas.Left="23" TextWrapping="Wrap" Text="seconds" Canvas.Top="475" Width="166" TextAlignment="Right" Style="{StaticResource SmallTextStyle}" Margin="0"/>
17
    <TextBlock x:Name="TimeSeconds" Height="205" Canvas.Left="3" TextWrapping="Wrap" Text="59" Canvas.Top="505" Width="210" FontSize="186.667" RenderTransformOrigin="0.5,0.5" Opacity="0">
18
        <TextBlock.RenderTransform>
19
            <CompositeTransform/>
20
        </TextBlock.RenderTransform>
21
    </TextBlock>
22
    <TextBlock x:Name="DateText" Height="39" Canvas.Left="208" TextWrapping="Wrap" Text="2012/12/31" Canvas.Top="258" Width="143" FontSize="29.333" Opacity="0"/>
23
</Canvas> 

Paso 3: Compartir código

Como se discutió anteriormente, el código que es común para ambas plataformas puede colocarse en el proyecto compartido. El código que usa APIs específicas para cada plataforma debe colocarse en uno de los proyectos específicos de plataforma. Incluso puedes usar directivas #ifdef para incluir código específico de plataforma en un proyecto compartido.

Ya que la aplicación Hex Clock Pro no usa APIs que sean específicas para cada plataforma, puedo colocar todo el código en el proyecto compartido.

Ocultando la barra de estado

En MainPage.xaml.cs del proyecto compartido hemos usado la directiva #ifdef para aislar código específico de Windows Phone. El código incluido entre #ifdef oculta la barra de estado en Windows Phone.

1
public MainPage()
2
{
3
    this.InitializeComponent();
4
    #if WINDOWS_PHONE_APP
5
    ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseCoreWindow);
6
    #endif
7
}

Mostrando la hora actual

He usado la clase DispatcherTimer para invocar un tic inicial al cargar la cuadrícula LayoutRoot. El objeto timer invoca a la función timer_Tick con cada tic del reloj.

1
try
2
{
3
    DispatcherTimer timer = new DispatcherTimer();
4
    timer.Tick += timer_Tick;
5
    timer.Interval = new TimeSpan(0, 0, 0, 1);
6
    timer.Start();
7
    timer_Tick(null, null);             //Call an initial tick

8
}
9
catch { }

La función timer_Tick actualiza la hora mostrada en la aplicación y al mismo tiempo actualiza el color de fondo.

Actualizando el color de fondo

El color de fondo tiene asignado un color hexadecimal que corresponde a la hora actual.

1
HexColour color = new HexColour(hexTime);
2
SolidColorBrush bgBrush = new SolidColorBrush(Color.FromArgb(color.A, color.R, color.G, color.B));
3
LayoutRoot.Background = bgBrush;

Un objeto de la clase HexColour es inicializado con la hora actual, devolviendo los valores RGB correspondientes. El constructor de la clase HexColour establece los valores A, R, G y B para el color especificado.

1
public HexColour(string hexCode)
2
{
3
    if (hexCode == null)
4
    {
5
        throw new ArgumentNullException("hexCode");
6
    }
7
8
    if (!Regex.IsMatch(hexCode, HEX_PATTERN))
9
    {
10
        throw new ArgumentException("Format must be #000000 or #FF000000 (no extra whitespace)", "hexCode");
11
    }
12
13
    // shave off '#' symbol

14
    hexCode = hexCode.TrimStart('#');
15
16
    // if no alpha value specified, assume no transparency (0xFF)

17
    if (hexCode.Length != LENGTH_WITH_ALPHA)
18
        hexCode = String.Format("FF{0}", hexCode);
19
20
    _color = new Color();
21
    _color.A = byte.Parse(hexCode.Substring(0, 2), NumberStyles.AllowHexSpecifier);
22
    if (_color.A < 50)
23
        _color.A = 50;
24
    _color.R = byte.Parse(hexCode.Substring(2, 2), NumberStyles.AllowHexSpecifier);
25
    _color.G = byte.Parse(hexCode.Substring(4, 2), NumberStyles.AllowHexSpecifier);
26
    _color.B = byte.Parse(hexCode.Substring(6, 2), NumberStyles.AllowHexSpecifier);
27
}

Añadiendo animaciones y efectos

He imitado la animación inicial usada en la aplicación de reloj anterior en Tuts+ y se inicializa cuando se carga LayoutRoot.

1
Storyboard sb = (Storyboard)this.Resources["IntialAnimation"];
2
sb.BeginTime = TimeSpan.FromSeconds(0.1);
3
sb.Begin();

Esto es todo lo que necesitamos para construir la aplicación Hex Clock Pro. La aplicación usa código compartido al 100%. Solamente necesitas generar paquetes de aplicación separados para ambas plataformas. La aplicación se ve muy similar en Windows Phone y usa el mismo código XAML para su interfaz de usuario.

Hex Clock Pro for Windows Phone 81Hex Clock Pro for Windows Phone 81Hex Clock Pro for Windows Phone 81

Toma en cuenta que he añadido todo el código XAML y C# en el proyecto compartido, pero al desplegar ya sea la aplicación de Windows o la de Windows Phone, el código del proyecto compartido se combina internamente con los proyectos específicos de cada plataforma.

Conclusión

La mayor parte del código de la aplicación de Windows y de Windows Phone es compartido y, aunque las interfaces de usuario estén separadas, estas son suficientemente similares, por lo que construir ambas representa menos trabajo que construir dos interfaces de usuario desde cero.

Si hubiera creado una versión de Windows Phone de Hex Clock Pro para Windows Phone 7 u 8, esto habría representado mucho más trabajo, ya que Windows Phone 7 no contiene APIs de WinRT y Windows Phone 8 solamente contiene un pequeño subconjunto.

Con Windows 10 veremos más convergencia, lo que significa tener una API (la API de WinRT) para múltiples plataformas, así como un alto grado de fidelidad entre los elementos de la interfaz de usuario para cada plataforma, lo que no impide que los desarrolladores usen elementos específicos para cada plataforma y así poder presentar la mejor experiencia posible en cada dispositivo. No dudes en descargar los archivos fuente del tutorial para usarlos como referencia. Hex Clock Pro también está disponible en el marketplace de Windows Phone 8.1 y Windows 8.1.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.