Seguro que alguna vez has sentido que te falta esa funcionalidad rápida en la pantalla de inicio de tu móvil sin tener que abrir la aplicación completa. Los widgets han estado con nosotros desde que Android era un niño, pero con la llegada de Android 12 han vuelto a ponerse de moda, obligándonos a repensar cómo presentamos la información de un vistazo.
Para hacernos la vida más fácil a los desarrolladores, Google ha lanzado Jetpack Glance, una librería que nos permite dejar atrás el tedioso XML tradicional y aprovechar el poder de Compose. Básicamente, es una forma de crear esas pequeñas ventanas interactivas usando un enfoque moderno y declarativo, aunque hay que tener claro que sigue operando bajo las reglas de RemoteViews, lo que implica algunas restricciones técnicas que debemos conocer.
Manos a la obra: Configuración inicial
Para empezar a montar tu widget, lo primero es preparar el terreno. Necesitas extender la clase GlanceAppWidgetReceiver. Este receptor es el corazón que comunica el sistema operativo con tu interfaz de Glance. En el código, deberás definir qué clase de widget quieres utilizar asignándola a la propiedad glanceAppWidget.
No olvides que el AndroidManifest.xml es donde ocurre la magia del registro. Debes declarar el receptor y añadirle un filtro de intents para la acción APPWIDGET_UPDATE. Además, es fundamental vincularlo a un archivo de metadatos XML mediante el elemento meta-data, que es donde definiremos las características físicas del widget.
Definiendo la apariencia y el tamaño
El archivo de recursos my_app_widget_info.xml es donde decides cuánto espacio ocupará tu creación. Aquí es donde configuramos el AppWidgetProviderInfo. Un punto curioso es que, a diferencia de los widgets antiguos, con Glance no necesitamos un XML de diseño inicial, aunque es muy recomendable usar el diseño de carga predefinido de la librería para que el usuario no vea un hueco vacío mientras se renderiza la interfaz.
En cuanto a las dimensiones, Android 12 introdujo los conceptos de targetCellWidth y targetCellHeight, que definen el tamaño basado en celdas de cuadrícula. Para que tu app sea compatible con versiones anteriores, lo ideal es jugar a dos bandas y definir también minWidth y minHeight en dp. De este modo, si el dispositivo es antiguo, el sistema hará el cálculo redondeando hacia arriba según la celda más cercana.
- ResizeMode: Permite decidir si el usuario puede estirar el widget horizontalmente, verticalmente o en ambos sentidos.
- Min/Max Resize: Establecen los límites absolutos para que la interfaz no se vuelva ilegible o quede demasiado gigante.
- UpdatePeriodMillis: Controla cada cuánto se refresca el contenido; ojo, que abusar de esto destruirá la batería del usuario, así que mejor no actualizar más de una vez por hora.
Construyendo la interfaz con Compose
La parte más divertida es crear la UI. Para ello, creamos una clase que herede de GlanceAppWidget y sobrescribimos el método provideGlance. Es aquí donde cargamos los datos necesarios. Un detalle técnico vital: este método corre en el hilo principal, así que si tienes que hacer una consulta pesada a la base de datos, usa withContext para moverte a un hilo secundario y no bloquear la app.
Dentro de provideContent, empezamos a usar los componentes de Glance. Aunque se parecen a los de Compose, son elementos específicos. Por ejemplo, podemos usar un Column para apilar elementos verticalmente o un Row para poner botones uno al lado del otro. Para darle interactividad, utilizamos acciones como actionStartActivity, que permite que el widget lance una actividad específica al hacer clic.
Detalles de acabado y optimización
Si quieres que tu widget se vea profesional, tienes que prestar atención a las esquinas redondeadas. Android 12 permite usar el radio del sistema mediante system_app_widget_background_radius. En Glance, esto se aplica fácilmente con el modificador cornerRadius. Para que todo quede niquelado en versiones viejas de Android, lo mejor es implementar recursos de temas personalizados que sirvan de alternativa.
Sobre la gestión de eventos, el GlanceAppWidgetReceiver se encarga de traducir los avisos del sistema en ciclos de vida de Compose. Tienes métodos como onUpdate para refrescar la vista o onDeleted para limpiar datos cuando el usuario borra el widget. Eso sí, ten mucho cuidado con el tiempo: los receptores tienen un límite estricto de 10 segundos. Si tu tarea es larga, no te la juegues y delega el trabajo a WorkManager.
La implementación de estas miniaturas interactivas permite crear experiencias fluidas y adaptables gracias a la integración de Jetpack Compose, optimizando desde el registro en el manifiesto y la gestión de dimensiones en XML hasta el renderizado dinámico de componentes y la adaptación de radios de esquina según la versión de Android del dispositivo. Comparte esta información para que otros usuarios conozcan del tema.