Cómo compilar caras de reloj para Wear OS

1. Antes de comenzar

Para crear caras de reloj para Wear OS, los desarrolladores deben usar el Formato de Caras de Relojes que está basado en XML y te permite crear caras de reloj expresivas y de alto rendimiento.

Este codelab está dirigido para quienes deseen crear caras de reloj de forma manual con XML o quienes quieran comprender mejor el formato para crear sus propias herramientas de diseño.

Si quieres usar herramientas gráficas para crear tu propia cara de reloj, te recomendamos que mires las herramientas existentes, como Watch Face Studio.

Requisitos previos

  • Experiencia con XML

Actividades

En este codelab, aprenderás lo siguiente:

  • Cómo se empaquetan las caras de reloj de WFF
  • Cómo crear una cara de reloj, incluido el modo ambiente
  • Cómo agregar elementos, como formas
  • Cómo incorporar fuentes de datos en la cara de reloj
  • Cómo solucionar problemas con tu cara de reloj

Crearás una cara de reloj personalizable, con una variedad de temas de colores para elegir, un contador de pasos integrado y un indicador de fecha.

90468c36ea8b7ca.png 324c4462145dbcc6.png

Requisitos

2. Información sobre la estructura de proyectos del Formato de Caras de Relojes

Descarga los archivos del codelab

Para comenzar, descarga los archivos del codelab aquí.

$ git clone https://github.com/android/codelab-watch-face-format

También tienes la opción de descargar el repositorio como archivo ZIP:

Hay dos proyectos en el directorio watch-face-format: start y finish. Usaremos el proyecto start, pero puedes consultar el proyecto finish en cualquier momento, ya que contiene el codelab terminado.

Inspeccionemos la estructura básica del proyecto de Formato de Caras de Relojes. Puedes usar el editor que elijas o abrir el proyecto de partida en Android Studio seleccionando File > Open… y el directorio start.

En el directorio start/watchface/src/main, verás los siguientes archivos. Veamos qué hace cada uno:

Archivo

Descripción

AndroidManifest.xml

Al igual que en una app para Android normal, este archivo contiene información esencial sobre la cara de reloj y lo que se necesita para compilarla.

res/xml/watch_face_info.xml

El archivo de información de la cara de reloj contiene metadatos sobre ella, como cómo encontrar la imagen de vista previa y si se puede personalizar.

res/raw/watchface.xml

Este archivo contiene la definición de la cara de reloj. Si bien es posible tener más de una definición, este es el archivo predeterminado que se usa.

res/drawable/preview.png

Cada cara de reloj necesita una imagen de vista previa que use el sistema. Para que se compile este proyecto, la carpeta start/ contiene una vista previa en blanco. La actualizaremos más adelante.

res/drawable/hour.pngres/drawable/minute.pngres/drawable/second.png

Estas son las manecillas del reloj que usaremos en nuestra cara de reloj.

res/values/strings.xml

Al igual que en una app para Android, contiene cadenas que se pueden usar en la cara de reloj.

¿Dónde está el código?

Observa que, en realidad, no hay código en el proyecto. Además del archivo AndroidManifest.xml, todos los archivos del proyecto residen en res/, el directorio de recursos. Esto se debe a que las caras de reloj del Formato de Caras de Relojes no pueden contener código. Por ejemplo, si intentas incluir código Kotlin o Java, Play Store no lo aceptará.

El sistema Wear OS lee estos recursos y se encarga de compilar y ejecutar tu cara de reloj por ti. Esto significa que no se necesita ningún entorno de ejecución ni ninguna otra lógica, lo que te ahorra esfuerzo de desarrollo.

3. Compila una cara de reloj

Actualizaremos cada uno de los archivos anteriores para crear una cara de reloj funcional.

Prepara el manifiesto

Para identificar el paquete como una cara de reloj del Formato de Caras de Relojes, el manifiesto debe declarar dos aspectos:

  1. Que no hay código en el proyecto
  2. Es la versión del Formato de Caras de Relojes que se usa

Primero, actualiza el elemento <application> para agregar el atributo hasCode:

<application
    android:label="@string/watch_face_name"
    android:hasCode="false">

En segundo lugar, agrega un <property> al elemento <application> que especifique la versión del Formato de Caras de Relojes que se usa en esta cara de reloj:

<property
    android:name="com.google.wear.watchface.format.version"
    android:value="1" />

Define el archivo watch_face_info

El archivo watch_face_info.xml tiene un requisito obligatorio: especificar la ubicación de la imagen de vista previa. En este proyecto, proporcionamos una imagen de vista previa en res/drawable/preview.png. Este es un archivo en blanco, pero lo actualizaremos más adelante con una captura de pantalla real de nuestra cara de reloj terminada.

Como parte del codelab, también haremos que nuestra cara de reloj sea personalizable. También lo declaramos en watch_face_info.xml file con el elemento <Editable>.

Actualiza res/xml/watch_face_info.xml para agregar los siguientes elementos:

<Preview value="@drawable/preview" />
<Editable value="true" />

Escribe XML de Formato de Caras de Relojes

La definición de la cara de reloj real se encuentra en res/raw/watchface.xml. Inspecciona este archivo en tu editor. Verás que el elemento <WatchFace> define un ancho y una altura de 450 por 450 para la cara de reloj. Este espacio de coordenadas se usa en todo el resto del archivo, independientemente de las dimensiones de píxeles reales en las que se ejecuta la cara de reloj, y se ajusta según corresponda.

El XML es el siguiente:

<?xml version="1.0"?>
<WatchFace width="450" height="450">
  <Scene>
    <PartText x="0" y="0" width="450" height="450">
      <Text>
        <Font family="SYNC_TO_DEVICE" size="48">Hello, World!</Font>
      </Text>
    </PartText>
  </Scene>
</WatchFace>

Por ahora, esta definición solo mostrará "Hello World!" en el reloj. Lamentablemente, aún no es la hora (pero volveremos a arreglar esto). Veamos cómo compilar la cara de reloj y cómo transferirla al dispositivo.

Compila e implementa la cara de reloj

En la línea de comandos, asegúrate de estar en el directorio de inicio y, luego, ingresa el siguiente comando:

./gradlew installDebug

O en Windows:

gradlew.bat installDebug

Se compilará la cara de reloj y se instalará en el dispositivo. Mantén presionada la pantalla de la cara de reloj y busca la cara de reloj Codelab. Como alternativa, para configurar la cara de reloj desde la línea de comandos, usa lo siguiente:

adb shell am broadcast -a com.google.android.wearable.app.DEBUG_SURFACE --es operation set-watchface --es watchFaceId com.example.codelab

Ahora deberías ver la cara de reloj en tu reloj o emulador. ¡Felicitaciones!

b1ab1ed6a1ce8575.png

4. Agrega la hora

El Formato de Caras de Relojes admite la visualización de relojes analógicos y digitales, incluso puedes tener ambos o varios en una sola cara de reloj.

Veamos cómo agregar un reloj analógico con el elemento < AnalogClock>. Primero, quita todo el elemento < PartText> del archivo watchface.xml y reemplázalo por lo siguiente:

<AnalogClock x="0" y="0" width="450" height="450">
  <!-- TODO: Add shadows here later -->
  <HourHand resource="hour"
      x="215" y="50" width="20" height="190"
      pivotX="0.5" pivotY="0.921" >
  </HourHand>
  <MinuteHand resource="minute"
      x="217" y="25" width="16" height="220"
      pivotX="0.5" pivotY="0.9">
  </MinuteHand>
  <SecondHand resource="second"
      x="221" y="15" width="8" height="245"
      pivotX="0.5" pivotY="0.857">
    <Variant mode="AMBIENT" target="alpha" value="0" />
    <Sweep frequency="15" />
  </SecondHand>
</AnalogClock>

El elemento <AnalogClock> tiene una altura y un ancho de 450, por lo que ocupa toda la pantalla. También tiene tres elementos secundarios: < HourHand>, < MinuteHand> y < SecondHand>. Ten en cuenta lo siguiente sobre cómo se definen:

  • Recurso: Cada uno de estos elementos secundarios tiene un atributo de recurso, que corresponde a un recurso de diseño. Por ejemplo, hay un archivo hour.png en res/drawable, que usa el elemento <HourHand>. Ten en cuenta que no es necesario especificar @drawable.
  • Reorientaciones: Las manecillas rotan automáticamente, pero pivotX y pivotY especifican dónde debe ocurrir la reorientación. A modo de ejemplo, pivotY se calcula de la siguiente manera:

f08428ae204605e1.png

c194bd487cebbe26.png

  • Variante: El <SecondHand> incluye un elemento secundario < Variant>, que oculta el segundero, ya que la cara de reloj solo se actualizará cada minuto cuando esté en modo ambiente.

Ahora, ejecuta el siguiente comando para volver a compilar y, luego, implementar la cara de reloj en tu dispositivo o emulador:

./gradlew installDebug

Esta vez, tenemos un reloj que funciona, aunque aún podemos hacer mucho para mejorarlo.

52628bf6c0d30d09.png

5. Agrega colores y temas

Parte de lo que hace que las caras de reloj sean divertidas es la capacidad de personalizarlas y hacerlas expresivas.

Nuestra cara de reloj es un poco simple en este momento, ya que es completamente blanca, así que agreguemos un poco de color. Además, hagamos que los temas de colores sean personalizables.

Crea el objeto ColorConfiguration

Primero, definiremos los temas de color que estarán disponibles en la cara de reloj. En watchface.xml, busca el texto <!-- TODO: Add UserConfigurations here --> y reemplázalo por lo siguiente:

<UserConfigurations>
  <ColorConfiguration id="themeColor" displayName="color_label" defaultValue="0">
    <ColorOption id="0" displayName="color_theme_0" colors="#ffbe0b #fb5607 #ff006e #8338ec #883c3c3c" />
    <ColorOption id="1" displayName="color_theme_1" colors="#8ecae6 #219ebc #ffb703 #fb8500 #883c3c3c" />
    <ColorOption id="2" displayName="color_theme_2" colors="#ff595e #ffca3a #8ac926 #1982c4 #883c3c3c" />
    <ColorOption id="3" displayName="color_theme_3" colors="#ff0000 #00ff00 #ff00ff #00ffff #883c3c3c" />
    <ColorOption id="4" displayName="color_theme_4" colors="#ff99c8 #fcf6bd #d0f4de #a9def9 #883c3c3c" />
    <ColorOption id="5" displayName="color_theme_5" colors="#1be7ff #6eeb83 #e4ff1a #ffb800 #883c3c3c" />
  </ColorConfiguration>
</UserConfigurations>

Esto define 6 temas de colores, cada uno con 5 colores. Cada tema es una lista de colores separados por espacios, como se muestra en el atributo colors.

Cada uno de los temas necesitará un nombre fácil de entender, por lo que debes agregar las siguientes definiciones al archivo res/values/strings.xml:

<string name="color_label">Color Theme</string>
<string name="color_theme_0">Bold</string>
<string name="color_theme_1">Magic</string>
<string name="color_theme_2">Breeze</string>
<string name="color_theme_3">Daytime</string>
<string name="color_theme_4">Relaxed</string>
<string name="color_theme_5">Smart</string>

Usa ColorConfiguration

Después de definir los temas de color, aplícalos a las manecillas del reloj agregando un atributo tintColor a cada una de ellas. Modifica watchface.xml de la siguiente manera:

<HourHand ... tintColor="[CONFIGURATION.themeColor.0]">
...
<MinuteHand ... tintColor="[CONFIGURATION.themeColor.1]">
...
<SecondHand ... tintColor="[CONFIGURATION.themeColor.2]">

<HourHand> hace referencia al primer color del tema seleccionado, <MinuteHand> al segundo color y <SecondHand> al tercero.

Vuelve a compilar y, luego, implementa la cara de reloj, como antes, y verás que ahora tiene color.

e382aaf41c7990d9.png

Además, si mantienes presionada la cara de reloj y presionas el botón de configuración, puedes elegir entre los 6 temas de colores.

79ffac91f7cabaf5.png

6. Agrega un color de fondo

Hay algunas otras cosas que podemos hacer para que esta cara de reloj se destaque. Agreguemos un diseño de fondo en negrita. Si bien el fondo seguirá siendo predominantemente negro, este toque de color ayudará a mejorar el aspecto.

Usaremos el elemento < PartDraw> del Formato de Caras de Relojes, que te permite crear una capa para dibujar primitivas, como líneas, rectángulos, óvalos y arcos. Reemplaza el texto <!-- TODO: Add the background design here --> por lo siguiente:

<Group x="100" y="100" width="250" height="250" name="background" alpha="127">
  <Variant mode="AMBIENT" target="alpha" value="0" />
  <PartDraw x="0" y="0" width="250" height="250">
    <Ellipse x="0" y="0" width="250" height="250">
      <Fill color="[CONFIGURATION.themeColor.3]" />
    </Ellipse>
    <Ellipse x="50" y="50" width="150" height="150">
      <Fill color="#000000" />
    </Ellipse>
  </PartDraw>
</Group>

Observa nuevamente el uso del elemento <Variant>; esto quitará nuestro anillo de fondo cuando esté en modo ambiente para minimizar la cantidad de píxeles iluminados.

Observa también cómo volvemos a usar el tema de color para seleccionar el color del anillo, de modo que se mantenga el diseño en todos los elementos de la cara de reloj.

710c8969df19226b.png

7. Valida tu cara de reloj

Antes de continuar con la mejora de la cara de reloj, exploremos cómo optimizar el proceso de desarrollo con el uso del validador de Formato de Caras de Relojes.

El validador es una herramienta que verifica la exactitud de tu XML, lo que te ahorra tiempo en la compilación y la implementación de una cara de reloj solo para descubrir que no funciona.

  1. Descarga el archivo JAR del validador desde el repositorio de GitHub.
  2. Ejecuta el validador en tu archivo watchface.xml.
java -jar wff-validator.jar 1 watchface/src/main/res/raw/watchface.xml

Si el XML de la cara de reloj es válido, verás un mensaje de confirmación. Sin embargo, si se encuentra un error, se mostrarán los detalles del error y la ubicación, por ejemplo:

SEVERE: [Line 18:Column 49]: cvc-complex-type.2.4.a: Invalid content was found starting with element 'PartDrw'

8. Usa fuentes de datos

El Formato de Caras de Relojes puede usar una variedad de fuentes de datos diferentes para que tu cara de reloj sea más útil.

Agreguemos dos fuentes de datos de uso general que ayudan a que tu cara de reloj sea más útil: la fecha actual (¿quién no se olvidó de la fecha antes?) y el recuento de pasos diario.

Cada uno de estos elementos se coloca en un contenedor < PartText>, que es una capa para realizar operaciones de texto.

Agrega la fecha

Reemplaza el texto <!-- TODO: Add the date/time element here --> por lo siguiente:

<PartText x="225" y="225" width="225" height="225">
  <Variant mode="AMBIENT" target="alpha" value="0" />
  <TextCircular centerX="0" centerY="0" width="415" height="415" startAngle="180" endAngle="90" align="CENTER" direction="COUNTER_CLOCKWISE">
    <Font family="SYNC_TO_DEVICE" size="28" color="[CONFIGURATION.themeColor.0]">
      <Template>
        <![CDATA[%d %s]]>
        <Parameter expression="[DAY]"/>
        <Parameter expression="[MONTH_S]"/>
      </Template>
    </Font>
  </TextCircular>
</PartText>

En el fragmento anterior, usamos < Template> para dar formato a dos fuentes de datos en una cadena. DAY es un número entero del 1 al 31 y MONTH_S ya es una cadena, por lo que usamos la expresión de formato %d %s para colocar el número entero y la cadena juntos.

Es recomendable rodear esto con un elemento CDATA, ya que evita que se incorporen espacios en blanco de forma accidental en la renderización, lo que puede afectar la posición y la alineación.

Por último, observa nuevamente cómo usamos el tema de color para asegurarnos de que esta última incorporación a la cara de reloj mantenga el tema existente.

Agrega el recuento de pasos

Reemplaza el texto <!-- TODO: Add the step count element here --> por lo siguiente:

<PartText x="0" y="0" width="225" height="225">
  <Variant mode="AMBIENT" target="alpha" value="0" />
  <TextCircular centerX="225" centerY="225" width="415" height="415" startAngle="270" endAngle="360" align="CENTER" direction="CLOCKWISE">
    <Font family="SYNC_TO_DEVICE" size="28" color="[CONFIGURATION.themeColor.2]">
      <Template>
        <![CDATA[%05d]]>
        <Parameter expression="[STEP_COUNT]"/>
      </Template>
    </Font>
  </TextCircular>
</PartText>

El Formato de Caras de Relojes admite una amplia variedad de fuentes de datos, y el recuento de pasos es una gran incorporación a cualquier cara de reloj, ya que le permite al usuario hacer un seguimiento de su movimiento y ejercicio diarios.

Compila y, luego, implementa la cara de reloj para verificar estas incorporaciones más recientes:

78cd5888c9e3a9a6.png

9. Retoques finales y vista previa

La atención a los detalles es fundamental en las caras de reloj, así que agreguemos algunos detalles finales adicionales.

Agrega sombras a la cara de reloj

Las manecillas de la cara de reloj funcionan bien en sus diferentes colores, pero se ven un poco planas en la cara de reloj. Reemplaza <!-- TODO: Add shadows here later --> por lo siguiente para agregar sombras detrás de las manecillas del reloj:

<HourHand resource="hour" x="220" y="55" width="20" height="190"
    pivotX="0.5" pivotY="0.921" tintColor="[CONFIGURATION.themeColor.4]">
  <Variant mode="AMBIENT" target="alpha" value="0" />
</HourHand>
<MinuteHand resource="minute" x="222" y="30" width="16" height="220"
    pivotX="0.5" pivotY="0.9" tintColor="[CONFIGURATION.themeColor.4]">
  <Variant mode="AMBIENT" target="alpha" value="0" />
</MinuteHand>
<SecondHand resource="second" x="226" y="20" width="8" height="245"
    pivotX="0.5" pivotY="0.857" tintColor="[CONFIGURATION.themeColor.4]">
  <Variant mode="AMBIENT" target="alpha" value="0" />
  <Sweep frequency="15" />
</SecondHand>

8b5959083acc5689.png

Todos los fabricantes de relojes conocidos tienen su logotipo en sus caras de reloj, así que agreguemos el nuestro. Por supuesto, usemos el logotipo de Android.

Sin embargo, como se trata de un reloj inteligente, hagamos algo diferente y agreguemos un logotipo que pueda moverse en respuesta al ángulo de la muñeca de quien lo usa.

Para ello, colocaremos nuestra imagen dentro de un elemento < Group> y, luego, usaremos un elemento < Transform> para aplicar una rotación al elemento <Group>, según el ángulo de la muñeca. Nuestra estructura se verá de la siguiente manera:

e738ca09c695ca93.png

El punto de reorientación predeterminado de un elemento está en el centro, por lo que no es necesario ajustar pivotX y pivotY de <Group>. Si aplicas un <Transform> a <Group>, se rotará <PartImage> alrededor de ese punto de pivote central.

En <Transform>, usamos la fuente de datos [ ACCELEROMETER_ANGLE_XY], que representa la suma de los ángulos en la dirección X e Y.

Reemplaza <!-- TODO: Add the Android logo --> por el siguiente fragmento:

<Group x="92" y="92" width="266" height="266" name="logo_container">
  <Variant mode="AMBIENT" target="alpha" value="0" />
  <Transform target="angle" mode="BY" value="0.1 * [ACCELEROMETER_ANGLE_XY]" />
  <PartImage x="97" y="0" width="72" height="72"
    tintColor="[CONFIGURATION.themeColor.2]">
    <Image resource="android"/>
  </PartImage>
</Group>

Vuelve a implementar la cara de reloj. Si usas un dispositivo físico, póntelo y mueve la muñeca para ver cómo se mueve el logotipo de Android. Si usas un emulador, abre los controles extendidos del emulador y manipula los ángulos X e Y en los sensores virtuales.

Actualiza la vista previa

¿Recuerdas que, al comienzo del codelab, vimos que hay un archivo preview.png, que el sistema usa para mostrar una vista previa de la cara de reloj? Ahora, actualicemos esto para que refleje mejor nuestra cara de reloj terminada.

La forma más fácil de generar una captura de pantalla es con el emulador. Con la cara de reloj en ejecución, haz clic en el botón de captura de pantalla:

6172ea8cc9309516.png

Asegúrate de que la captura esté configurada en Display Shape:

9d90300c3ce4d8f.png

Guarda la imagen y reemplaza el archivo res/drawable/preview.png por esta imagen nueva. Vuelve a compilar y, luego, implementa la cara de reloj como antes.

10. Felicitaciones

¡Felicitaciones! Aprendiste los conceptos básicos para crear una cara de reloj con el Formato de Caras de Relojes.

Solución del codelab

Puedes obtener el código de la solución de este codelab en GitHub:

$ git clone https://github.com/android/codelab-watch-face-format

También tienes la opción de descargar el repositorio como archivo ZIP:

Próximos pasos

Hay mucho más que puedes hacer con el Formato de Caras de Relojes. Estas son algunas sugerencias sobre qué hacer a continuación:

Mejora tu cara de reloj

Prepárate para publicar

  • Consulta la herramienta de espacio en memoria, que analiza el uso de memoria de tu cara de reloj y es una herramienta esencial para usar antes de subirla a Google Play.