Widget es un elemento compacto de interfaz de usuario en la pantalla de inicio de iOS o Android que muestra información relevante sin abrir la aplicación. Los widgets aparecieron en iOS 14 (2020) con el framework WidgetKit en SwiftUI y existen en Android desde la versión 1.5 mediante AppWidgetProvider en Kotlin o Java. Permiten al usuario ver el clima, tipo de cambio, calendario, notas o estado de tareas directamente en la pantalla de inicio, ahorrando tiempo y simplificando la interacción. Según Apple, los usuarios interactúan con los widgets en promedio 4–6 veces al día, y colocar un widget en la pantalla de inicio aumenta la participación en la aplicación en un 20–30%. Para Android, estas cifras son comparables. Analicemos cómo funcionan los widgets en ambas plataformas con ejemplos de código.
Puntos clave
Widget es un elemento compacto de interfaz de usuario colocado en la pantalla de inicio de un dispositivo móvil para mostrar información relevante de una aplicación. A diferencia de una aplicación completa, un widget no requiere ejecutarse — el usuario ve los datos inmediatamente después de desbloquear la pantalla. El concepto proviene de los sistemas operativos de escritorio (macOS Dashboard, Windows Sidebar), y en el entorno móvil, Android introdujo soporte para widgets desde su primer lanzamiento (Android 1.5 Cupcake, 2009), mientras que Apple los agregó solo en iOS 14.
La implementación técnica difiere entre plataformas. Un widget de iOS es un target separado en Xcode, compilado como Widget Extension, que se ejecuta en su propio proceso. Un widget de Android es un BroadcastReceiver que extiende AppWidgetProvider y renderiza el diseño mediante RemoteViews. Ambas plataformas imponen restricciones estrictas de rendimiento y memoria: el sistema puede eliminar el widget si se exceden los límites. iOS limita los widgets a 30–50 MB y el tiempo de generación del timeline a 10 segundos. Android — intervalo de actualización no superior a 30 minutos mediante updatePeriodMillis y terminación forzada si onUpdate se bloquea.
Smart Stack en iOS y pilas en Android permiten al usuario agrupar varios widgets en un solo espacio de la pantalla de inicio. El dispositivo cambia automáticamente el widget mostrado según la hora del día, ubicación o actividad del usuario. Por ejemplo, por la mañana se muestra el calendario, durante el día — el clima, por la noche — las notas. Para los desarrolladores, esto significa que el widget debe funcionar correctamente como parte de una pila y no depender de una visualización constante.
WidgetKit es el framework de Apple para crear widgets en iOS 14+, iPadOS 14+ y macOS 11+. Los widgets se escriben en Swift usando SwiftUI y el mecanismo TimelineProvider para la actualización de contenido. La arquitectura de WidgetKit incluye tres componentes: TimelineProvider — una fuente de datos que forma una línea de tiempo con entradas; Widget Entry View — una Vista SwiftUI que muestra contenido basado en una entrada; Widget Configuration — una descripción del tipo, tamaños y familias del widget.
WidgetKit gestiona las actualizaciones automáticamente — el desarrollador no puede forzar una actualización del widget más frecuente de lo que el sistema permite. Apple utiliza un presupuesto de actualizaciones distribuido entre todos los widgets del dispositivo. El intervalo mínimo es de 15 a 30 minutos. Para datos críticos (por ejemplo, estado de entrega), se utiliza push-to-refresh — envío de una notificación push con una fecha futura relevante, tras la cual WidgetKit solicita un nuevo timeline. A partir de iOS 17, los widgets admiten interactividad mediante App Intents — los usuarios pueden presionar botones dentro de un widget sin abrir la aplicación.
| Tamaño | iOS (pt) | Contenido |
|---|---|---|
| Small | 170 × 170 | 1–2 indicadores: temperatura, tipo de cambio |
| Medium | 360 × 170 | 2–4 indicadores: pronóstico de 5 días, lista |
| Large | 360 × 380 | 5–10 indicadores: calendario, feed de noticias |
AppWidgetProvider es la clase base para crear widgets en Android, parte del SDK de Android desde API level 3. Un widget de Android es un BroadcastReceiver que recibe eventos de actualización, activación y desactivación del sistema. A diferencia de iOS, donde el widget se renderiza con SwiftUI en su propio motor, Android utiliza RemoteViews — un conjunto limitado de componentes View renderizados en el proceso del sistema (launcher). No se pueden usar Views personalizadas, animaciones complejas ni bibliotecas de UI.
El flujo de trabajo del widget Android incluye cuatro etapas. Configuración — al agregar un widget a la pantalla, el sistema puede iniciar una Activity de configuración donde el usuario selecciona ajustes. Actualización — el sistema llama a onUpdate() en un intervalo determinado (mínimo 30 minutos) o mediante una señal de la aplicación a través de WorkManager. Renderizado — el proveedor crea RemoteViews con datos actuales y los pasa mediante AppWidgetManager. Manejo de toques — el widget admite PendingIntent para botones: al hacer clic se abre una Activity o se realiza una acción. A partir de Android 12, los widgets obtuvieron soporte para esquinas redondeadas, colores adaptativos de Material You y cambios dinámicos de tamaño.
Creemos un widget de clima en Swift usando WidgetKit y SwiftUI. El proyecto debe incluir un target Widget Extension, agregado en Xcode mediante File → New → Target → Widget Extension.
import WidgetKit
import SwiftUI
// 1. Modelo de datos para el widget
struct WeatherEntry: TimelineEntry {
let date: Date
let temperature: Int
let condition: String
}
// 2. TimelineProvider — proveedor de datos
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> WeatherEntry {
WeatherEntry(date: Date(), temperature: 22, condition: "Soleado")
}
func getSnapshot(in context: Context, completion: @escaping (WeatherEntry) -> Void) {
let entry = WeatherEntry(date: Date(), temperature: 22, condition: "Soleado")
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<WeatherEntry>) -> Void) {
let now = Date()
let entry = WeatherEntry(date: now, temperature: 20, condition: "Nublado")
let nextUpdate = Calendar.current.date(byAdding: .hour, value: 3, to: now)!
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline)
}
}
// 3. Vista SwiftUI para mostrar
struct WeatherWidgetEntryView: View {
var entry: WeatherEntry
var body: some View {
VStack(alignment: .leading) {
Text("Clima").font(.caption).foregroundColor(.secondary)
HStack {
Text("\(entry.temperature)°").font(.largeTitle).fontWeight(.bold)
Spacer()
Text(entry.condition).font(.body)
}
}.padding()
}
}
// 4. Configuración del widget
@main
struct WeatherWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "WeatherWidget", provider: Provider()) { entry in
WeatherWidgetEntryView(entry: entry)
}
.configurationDisplayName("Clima")
.description("Muestra la temperatura actual")
.supportedFamilies([.systemSmall, .systemMedium])
}
}
Puntos clave: TimelineProvider determina cuándo y qué datos mostrar; getTimeline crea una línea de tiempo con la política de actualización .after(nextUpdate); StaticConfiguration conecta el proveedor con la Vista. Para datos dinámicos, se utiliza IntentConfiguration con parámetros personalizados.
Implementemos un widget de clima similar en Kotlin con AppWidgetProvider y RemoteViews.
// WeatherWidgetProvider.kt
class WeatherWidgetProvider : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onAppWidgetOptionsChanged(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int,
newOptions: Bundle
) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
companion object {
fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int
) {
val temperature = 20
val condition = "Nublado"
val views = RemoteViews(
context.packageName, R.layout.widget_weather
).apply {
setTextViewText(R.id.tv_temperature, "$temperature°")
setTextViewText(R.id.tv_condition, condition)
setOnClickPendingIntent(
R.id.widget_root, PendingIntent.getActivity(
context, 0,
Intent(context, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
)
}
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
// AndroidManifest — registro del proveedor
<receiver android:name=".WeatherWidgetProvider" android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_weather_info" />
</receiver>
El archivo widget_weather_info.xml establece los tamaños mínimos, intervalo y diseño: minWidth 160dp, minHeight 80dp, updatePeriodMillis 3600000 (1 hora). RemoteViews utiliza solo componentes compatibles: LinearLayout, TextView, ImageView. Las Views personalizadas y ConstraintLayout están disponibles desde Android 5.0. GlanceLayout — un enfoque experimental basado en Compose para RemoteViews — apareció en Android 15.
Preguntas frecuentes
iOS WidgetKit ofrece tres tamaños fijos (small, medium, large) y actualización mediante TimelineProvider con presupuesto del sistema. Android AppWidgetProvider utiliza tamaños flexibles basados en celdas, RemoteViews para renderizar y actualización mediante updatePeriodMillis o WorkManager.
En iOS, el sistema controla las actualizaciones — el intervalo mínimo es de 15 a 30 minutos, para datos críticos se utiliza push-to-refresh. En Android, el intervalo se establece en updatePeriodMillis (mínimo 30 minutos) o mediante WorkManager para tareas en segundo plano.
iOS soporta small (170x170pt), medium (360x170pt) y large (360x380pt). Android utiliza una cuadrícula flexible de celdas: de 2x1 a 5x5, el tamaño depende del launcher y la versión del SO.
En iOS, las animaciones dentro de los widgets no están disponibles — son elementos estáticos. Android RemoteViews admite animaciones básicas mediante setFloat() y ViewPropertyAnimator, pero las animaciones complejas no están disponibles.
Con una implementación adecuada — no. El sistema limita estrictamente los recursos del widget: en iOS — presupuesto de actualización y memoria (30–50 MB), en Android — intervalo mínimo de actualización. Los widgets problemáticos son terminados forzosamente por el sistema.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también