Los widgets de apps son vistas en miniatura de una app que puedes incorporar en otros aplicaciones, como la pantalla de inicio, y recibir actualizaciones periódicas. Estos se denominan widgets en la interfaz de usuario, y puedes publicar uno con el proveedor de widgets de la app (o el proveedor de widgets). Un componente de la aplicación que que contiene otros widgets se denomina host de widget de la app (o host de widget). Figura 1 muestra un widget de música de muestra:
En este documento, se describe cómo publicar un widget usando un proveedor de widgets. Para
detalles sobre cómo crear tu propio AppWidgetHost
para
widgets de apps host, consulta Cómo compilar un host de widgets.
Para obtener información sobre cómo diseñar el widget, consulta Descripción general de los widgets de apps.
Componentes del widget
Para crear un widget, necesitas los siguientes componentes básicos:
- Objeto
AppWidgetProviderInfo
- Describe los metadatos para un widget, como su diseño, la actualización
la frecuencia y la clase
AppWidgetProvider
.AppWidgetProviderInfo
se define en XML, como que se describe en este documento. - Clase
AppWidgetProvider
- Define los métodos básicos que te permiten interactuar de manera programática con el
widget. A través de él, recibes emisiones cuando se actualiza el widget
habilitar, inhabilitar o borrar. Declaras
AppWidgetProvider
en las en el manifiesto y, luego, implementarlo, que se describe en este documento. - Diseño de la vista
- Define el diseño inicial del widget. El diseño se define en XML, como se describe en este documento.
En la Figura 2, se muestra cómo se ajustan estos componentes al procesamiento general del widget de la app. de tu flujo de trabajo.
Si tu widget necesita que el usuario configure el widget de la app, actividad. Esta actividad permite que los usuarios modifiquen la configuración del widget; por ejemplo, el la zona horaria para un widget de reloj.
- A partir de Android 12 (nivel de API 31), puedes proporcionar una y permite que los usuarios reconfiguren el widget más tarde. Consulta Usa el configuración predeterminada del widget y Habilitar que los usuarios reconfiguren los widgets colocados para obtener más información.
- En Android 11 (nivel de API 30) o versiones anteriores, esta actividad se inicia cada vez el usuario agrega el widget a su pantalla principal.
También recomendamos las siguientes mejoras: diseños flexibles de widgets, mejoras varias, widgets avanzados, widgets de colecciones y creación de widgets. del servidor.
Declara el XML de AppWidgetProviderInfo
El objeto AppWidgetProviderInfo
define las cualidades esenciales de un widget.
Define el objeto AppWidgetProviderInfo
en un archivo de recursos XML con un solo
elemento <appwidget-provider>
y guárdalo en la carpeta res/xml/
del proyecto.
Esto se muestra en el siguiente ejemplo:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:maxResizeWidth="250dp"
android:maxResizeHeight="120dp"
android:updatePeriodMillis="86400000"
android:description="@string/example_appwidget_description"
android:previewLayout="@layout/example_appwidget_preview"
android:initialLayout="@layout/example_loading_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
Atributos de tamaño de widgets
La pantalla principal predeterminada coloca los widgets en su ventana en función de una cuadrícula de celdas. que tienen una altura y un ancho definidos. La mayoría de las pantallas principales solo permiten que los widgets adopten tamaños que son múltiplos enteros de las celdas de la cuadrícula, por ejemplo, dos celdas horizontalmente por tres celdas en vertical.
Los atributos de tamaño del widget te permiten especificar un tamaño predeterminado para este y proporcionar límites inferior y superior para el tamaño del widget. En este contexto, el tamaño predeterminado de un widget es el tamaño que este toma cuando se inicia por primera vez agregado a la pantalla de inicio.
En la siguiente tabla, se describen los atributos <appwidget-provider>
correspondientes
tamaño del widget:
Atributos y descripción | |
---|---|
targetCellWidth y
targetCellHeight (Android 12),
minWidth y minHeight |
targetCellWidth y
targetCellHeight , minWidth y
minHeight , para que tu app pueda volver a usar
minWidth y minHeight si el dispositivo del usuario
no es compatible con targetCellWidth y
targetCellHeight Si es compatible, el
Atributos targetCellWidth y targetCellHeight
tienen prioridad sobre minWidth y minHeight
atributos.
|
minResizeWidth y
minResizeHeight |
Especifica el tamaño mínimo absoluto del widget. Estos valores especifican la
tamaño en el que el widget es ilegible o inutilizable. Usando
Estos atributos permiten al usuario cambiar el tamaño del widget a un tamaño menor.
que el tamaño predeterminado del widget. El atributo minResizeWidth tiene las siguientes características:
se ignora si es mayor que minWidth o si es horizontal
el cambio de tamaño no está habilitado. Consulta
resizeMode Del mismo modo, el
el atributo minResizeHeight se ignora si es mayor que
minHeight o si no está habilitado el cambio de tamaño vertical. |
maxResizeWidth y
maxResizeHeight |
Especifica el tamaño máximo recomendado del widget. Si los valores no son
un múltiplo de las dimensiones de las celdas de la cuadrícula, se redondean hasta la más cercana
tamaño de celda. El atributo maxResizeWidth se ignora si es
inferior a minWidth o si el cambio de tamaño horizontal no es
habilitado. Consulta resizeMode . Del mismo modo,
el atributo maxResizeHeight se ignora si es mayor
que minHeight o si el cambio de tamaño vertical no está habilitado.
Se introdujo en Android 12. |
resizeMode |
Especifica las reglas mediante las cuales se puede cambiar el tamaño de un widget. Puedes usar esta
para hacer que los widgets de la pantalla principal puedan cambiar de tamaño de forma horizontal o vertical.
o en ambos ejes. Los usuarios toquen y mantén presionado un widget para mostrar sus controladores de cambio de tamaño,
luego arrastra los controladores horizontales o verticales para cambiar su tamaño en la
cuadrícula de diseño. Entre los valores del atributo resizeMode , se incluyen los siguientes:
horizontal , vertical y none . Para
declara que un widget puede cambiar de tamaño horizontal y verticalmente, usa
horizontal|vertical |
Ejemplo
Para ilustrar cómo los atributos de la tabla anterior afectan el tamaño del widget, supón las siguientes especificaciones:
- Una celda de cuadrícula tiene 30 dp de ancho y 50 dp de alto.
- Se proporciona la siguiente especificación de atributo:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:maxResizeWidth="120dp"
android:maxResizeHeight="120dp"
android:resizeMode="horizontal|vertical" />
A partir de Android 12:
Usa los atributos targetCellWidth
y targetCellHeight
como valores predeterminados.
tamaño del widget.
De forma predeterminada, el tamaño del widget es 2x2. Se puede reducir el tamaño del widget a 2 x 1. de hasta 4 × 3.
Android 11 y versiones anteriores:
Usa los atributos minWidth
y minHeight
para calcular el tamaño predeterminado de
el widget.
El ancho predeterminado = Math.ceil(80 / 30)
= 3
La altura predeterminada = Math.ceil(80 / 50)
= 2
De forma predeterminada, el tamaño del widget es 3x2. Se puede reducir el tamaño del widget a 2 x 1. en pantalla completa.
Atributos adicionales del widget
En la siguiente tabla, se describen los atributos <appwidget-provider>
correspondientes
a cualidades que no sean
el tamaño de widgets.
Atributos y descripción | |
---|---|
updatePeriodMillis |
Define la frecuencia con la que el framework del widget solicita una actualización desde el
AppWidgetProvider llamando a onUpdate()
de devolución de llamada. No se garantiza que la actualización real ocurra exactamente el
tiempo con este valor, y te recomendamos que actualices
posible, no más de una vez por hora, para conservar la batería.
Para ver la lista completa de consideraciones para elegir un período de actualización adecuado,
ver
Optimizaciones para actualizar el widget
contenido. |
initialLayout |
Apunta al recurso de diseño que define el diseño del widget. |
configure |
Define la actividad que se inicia cuando el usuario agrega el widget. lo que les permite configurar las propiedades de los widgets. Consulta Permite que los usuarios configuren widgets. A partir de Android 12, la app puede omitir la configuración. Consulta Usa el configuración predeterminada del widget para obtener más detalles. |
description |
Especifica la descripción para que el selector del widget se muestre para tu widget. Se introdujo en Android 12. |
previewLayout (Android 12)
y previewImage (Android 11 y versiones anteriores) |
previewImage .
y previewLayout para que tu app pueda recurrir
al uso de previewImage si el dispositivo del usuario no es compatible
previewLayout Para obtener más detalles, consulta
Retrocompatibilidad con modelos
vistas previas de widgets.
|
autoAdvanceViewId |
Especifica el ID de vista de la subvista del widget que avanza automáticamente el host del widget. |
widgetCategory |
Declara si tu widget se puede mostrar en la pantalla principal.
(home_screen ), la pantalla de bloqueo (keyguard ) o
ambos. Para Android 5.0 y versiones posteriores, solo es válido home_screen .
|
widgetFeatures |
Declara las funciones compatibles con el widget. Por ejemplo, si quieres
que tu widget use su configuración predeterminada cuando un usuario lo agregue, especifica
tanto
configuration_optional
y
reconfigurable
marcas. De esta manera, se evita iniciar la actividad de configuración después de que un usuario
agrega el widget. El usuario aún puede
reconfigura el widget
después. |
Cómo usar la clase AppWidgetProvider para controlar las transmisiones del widget
La clase AppWidgetProvider
controla las transmisiones del widget y lo actualiza.
en respuesta a eventos de ciclo de vida de widgets. En las siguientes secciones, se describe cómo
declara AppWidgetProvider
en el manifiesto y, luego, impleméntalo.
Declara un widget en el manifiesto
Primero, declara la clase AppWidgetProvider
en el archivo AndroidManifest.xml
de tu app.
como se muestra en el siguiente ejemplo:
<receiver android:name="ExampleAppWidgetProvider"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
El elemento <receiver>
requiere el atributo android:name
, que especifica
el AppWidgetProvider
que usa el widget. No se debe exportar el componente
a menos que se deba transmitir un proceso separado a tu AppWidgetProvider
, lo que
no suele ser el caso.
El elemento <intent-filter>
debe incluir un elemento <action>
con el
atributo android:name
. Este atributo especifica que el AppWidgetProvider
acepta el
ACTION_APPWIDGET_UPDATE
transmisión. Esta es la única emisión que debes declarar de manera explícita. El
AppWidgetManager
envía automáticamente todas las demás transmisiones de widgets al AppWidgetProvider
como
necesario.
El elemento <meta-data>
especifica el recurso AppWidgetProviderInfo
y
requiere los siguientes atributos:
android:name
: Especifica el nombre de los metadatos. Usaandroid.appwidget.provider
para identificar los datos DescriptorAppWidgetProviderInfo
.android:resource
: Especifica el recursoAppWidgetProviderInfo
. ubicación.
Implementa la clase AppWidgetProvider
La clase AppWidgetProvider
extiende
BroadcastReceiver
como
de conveniencia para manejar las transmisiones de widgets. Solo recibe el evento
relevantes para el widget, como cuando se actualiza el widget,
borrar, habilitar e inhabilitar. Cuando ocurren estos eventos de transmisión,
Se llama a los métodos AppWidgetProvider
de la siguiente manera:
onUpdate()
- Se llama a este método para actualizar el widget en intervalos definidos por el
El atributo
updatePeriodMillis
enAppWidgetProviderInfo
Consulta la tabla atributos adicionales del widget en esta página para más información. - También se llama a este método cuando el usuario agrega el widget, de modo que realiza
configuración esencial, como la definición de controladores de eventos para
Objetos
View
o trabajos iniciales a los que se cargarán datos mostrar en el widget. Sin embargo, si declaras una actividad de configuración sin la marcaconfiguration_optional
, no se llama a este método cuando el usuario agrega el widget, pero se llama para las actualizaciones posteriores. Es el responsabilidad de la actividad de configuración para realizar la primera actualización cuando configuración esté completa. Consulta Cómo permitir que los usuarios configuren widgets de apps para obtener más información. - La devolución de llamada más importante es
onUpdate()
. Consulta Controla eventos con el ClaseonUpdate()
de esta página para obtener más información. onAppWidgetOptionsChanged()
Se llama a este método cuando se coloca el widget por primera vez y cada vez que se lo coloca se ha cambiado el tamaño. Usa esta devolución de llamada para ocultar o mostrar contenido según el tamaño del widget o rangos. Obtén los rangos de tamaño y, a partir de Android 12, la lista de tamaños posibles que puede tomar una instancia de widget, llamando
getAppWidgetOptions()
: que devuelve unBundle
que incluye el lo siguiente:OPTION_APPWIDGET_MIN_WIDTH
: contiene el límite inferior del ancho, en unidades dp, de una instancia de widget.OPTION_APPWIDGET_MIN_HEIGHT
: contiene el límite inferior de la altura, en unidades dp, de una instancia de widget.OPTION_APPWIDGET_MAX_WIDTH
: contiene el límite superior del ancho, en unidades dp, de una instancia de widget.OPTION_APPWIDGET_MAX_HEIGHT
: contiene el límite superior de la altura, en unidades dp, de una instancia de widget.OPTION_APPWIDGET_SIZES
: contiene la lista de tamaños posibles (List<SizeF>
), en unidades dp, que un que puede tomar la instancia de widget. Se introdujo en Android 12.
onDeleted(Context, int[])
Se llama a este método cada vez que se borra un widget del host del widget.
onEnabled(Context)
Se llama a este método cuando se crea una instancia del widget por primera vez. Por ejemplo, si el usuario agrega dos instancias de tu widget, esto solo se llamará primera vez. Si necesitas abrir una base de datos nueva o realizar otra configuración que solo debe ocurrir una vez para todas las instancias de widgets, este es un buen lugar para hazlo.
onDisabled(Context)
Se llama a este método cuando se borra la última instancia de tu widget desde la host de widgets. Aquí es donde limpias cualquier trabajo realizado en
onEnabled(Context)
, como borrar una base de datos temporal.onReceive(Context, Intent)
Se llama a este método para cada transmisión y antes de cada devolución de llamada anterior. . Por lo general, no es necesario implementar este método, ya que la configuración La implementación de
AppWidgetProvider
filtra todas las transmisiones de widgets y llama al métodos anteriores según corresponda.
Debes declarar tu implementación de la clase AppWidgetProvider
como una transmisión.
con el elemento <receiver>
en AndroidManifest
. Consulta Cómo declarar un
en el manifiesto de esta página para obtener más información.
Cómo controlar eventos con la clase onUpdate()
La devolución de llamada AppWidgetProvider
más importante es onUpdate()
, porque es
se llama cuando cada widget se agrega a un host, a menos que uses una configuración
sin la marca configuration_optional
. Si el widget acepta alguna
de interacción del usuario y, luego, registra los controladores de eventos en esta devolución de llamada. Si
tu widget no crea archivos temporales o bases de datos, ni realiza otras tareas
que requiere limpieza, entonces onUpdate()
podría ser el único método de devolución de llamada que
definir.
Por ejemplo, si quieres un widget con un botón que inicie una actividad cuando
puedes usar la siguiente implementación de AppWidgetProvider
:
Kotlin
class ExampleAppWidgetProvider : AppWidgetProvider() { override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Perform this loop procedure for each widget that belongs to this // provider. appWidgetIds.forEach { appWidgetId -> // Create an Intent to launch ExampleActivity. val pendingIntent: PendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ Intent(context, ExampleActivity::class.java), /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // Get the layout for the widget and attach an onClick listener to // the button. val views: RemoteViews = RemoteViews( context.packageName, R.layout.appwidget_provider_layout ).apply { setOnClickPendingIntent(R.id.button, pendingIntent) } // Tell the AppWidgetManager to perform an update on the current // widget. appWidgetManager.updateAppWidget(appWidgetId, views) } } }
Java
public class ExampleAppWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Perform this loop procedure for each widget that belongs to this // provider. for (int i=0; i < appWidgetIds.length; i++) { int appWidgetId = appWidgetIds[i]; // Create an Intent to launch ExampleActivity Intent intent = new Intent(context, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ intent, /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // Get the layout for the widget and attach an onClick listener to // the button. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent); // Tell the AppWidgetManager to perform an update on the current app // widget. appWidgetManager.updateAppWidget(appWidgetId, views); } } }
Este AppWidgetProvider
define solo el método onUpdate()
y lo usa para lo siguiente:
crea un PendingIntent
que inicie
un objeto Activity
y lo adjunta al archivo
con setOnClickPendingIntent(int,
PendingIntent)
. Incluye un bucle que se itera a través de cada entrada
en appWidgetIds
, que es un array de IDs que identifican cada widget creado por
este proveedor. Si el usuario crea más de una instancia del widget, entonces
se actualizan todos al mismo tiempo. Sin embargo, solo hay un programa de updatePeriodMillis
se administra para todas las instancias del widget. Por ejemplo, si el cronograma de actualización
se define para que sea cada dos horas, y se agrega una segunda instancia del widget
una hora después de la primera, ambas se actualizarán en el período definido por
el primero, y el segundo período de actualización se ignora. Se actualizan cada dos
horas, no cada hora.
Consulta la
ExampleAppWidgetProvider.java
para obtener más información.
Recibir intents de transmisión de widget
AppWidgetProvider
es una clase de conveniencia. Si deseas recibir el widget
directamente, puedes implementar tu propio BroadcastReceiver
o anular
el
Devolución de llamada onReceive(Context,Intent)
. Los intents a los que debes prestar atención son los
lo siguiente:
ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED
Cómo crear el diseño del widget
Debes definir un diseño inicial para tu widget en XML y guardarlo en el
directorio res/layout/
del proyecto. Consulta Diseño
lineamientos para obtener más información.
Crear el diseño del widget es sencillo si conoces
diseños. Sin embargo, ten en cuenta que el widget
los diseños se basan en RemoteViews
,
que no es compatible con todo tipo de diseño o widget de vista. No puedes usar la función
Vistas o subclases de las vistas compatibles con RemoteViews
.
RemoteViews
también admite ViewStub
,
un objeto View
invisible de tamaño cero que puedes usar para aumentar el diseño de forma diferida.
recursos en el entorno de ejecución.
Compatibilidad con comportamientos con estado
En Android 12, se agrega compatibilidad con comportamientos con estado mediante lo siguiente componentes existentes:
El widget todavía no tiene un estado. La app debe almacenar el estado y registrarse para los eventos de cambio de estado.
En el siguiente ejemplo de código, se muestra cómo implementar estos componentes.
Kotlin
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true) // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2) // Listen for check changes. The intent has an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent) )
Java
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true); // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2); // Listen for check changes. The intent has an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));
Proporciona dos diseños: uno orientado a dispositivos que ejecutan Android 12 o
más alto en res/layout-v31
y la anterior
Android 11 o versiones anteriores en la carpeta predeterminada res/layout
Cómo implementar esquinas redondeadas
Android 12 presenta los siguientes parámetros del sistema para establecer la radios de las esquinas redondeadas de tu widget:
system_app_widget_background_radius
: el radio de la esquina del fondo del widget, que nunca es mayor que 28 dp.system_app_widget_inner_radius
: el radio de la esquina de cualquier vista dentro del widget. Significa exactamente 8 dp menor que el radio de fondo, para alinearse bien cuando se usa un valor de 8 dp con padding.
En el siguiente ejemplo, se muestra un widget que usa system_app_widget_background_radius
para su esquina y system_app_widget_inner_radius
para las vistas dentro de este.
1 Esquina del widget.
2 Esquina de una vista dentro del widget.
Consideraciones importantes sobre las esquinas redondeadas
- Los selectores externos y los fabricantes de dispositivos pueden anular la
system_app_widget_background_radius
tenga un tamaño inferior a 28 dp. El parámetrosystem_app_widget_inner_radius
siempre es 8 dp menor que el valor desystem_app_widget_background_radius
- Si el widget no usa
@android:id/background
ni define un fondo que recorta su contenido en función del esquema, conandroid:clipToOutline
establecido entrue
, el selector identifica automáticamente el fondo y recorta el widget con un rectángulo con esquinas redondeadas de hasta 16 dp. Consulta Asegúrate de que el widget sea compatible con Android 12
Para ofrecer compatibilidad de widgets con versiones anteriores de Android, recomendamos definir atributos personalizados y usar un tema personalizado para anularlos Android 12, como se muestra en los siguientes archivos en formato XML de ejemplo:
/values/attrs.xml
<resources>
<attr name="backgroundRadius" format="dimension" />
</resources>
/values/styles.xml
<resources>
<style name="MyWidgetTheme">
<item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
</style>
</resources>
/values-31/styles.xml
<resources>
<style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
</style>
</resources>
/drawable/my_widget_background.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="?attr/backgroundRadius" />
...
</shape>
/layout/my_widget_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:background="@drawable/my_widget_background" />