Creare un widget semplice

Prova il modo di comporre
Jetpack Compose è il toolkit per la UI consigliato per Android. Scopri come creare widget utilizzando API in stile Compose.

I widget delle app sono visualizzazioni in miniatura delle app che puoi incorporare in altre app, ad esempio la schermata Home, e ricevere aggiornamenti periodici. Queste visualizzazioni sono chiamate widget nell'interfaccia utente e puoi pubblicarne uno con un fornitore di widget per app (o fornitore di widget). Un componente dell'app che contiene altri widget è chiamato host di widget dell'app (o host di widget). La figura 1 mostra un esempio di widget musicale:

Esempio di widget musicale
Figura 1. Esempio di un widget musicale.

Questo documento descrive come pubblicare un widget utilizzando un fornitore di widget. Per informazioni dettagliate sulla creazione del tuo AppWidgetHost per ospitare i widget delle app, vedi Creare un host di widget.

Per informazioni su come progettare il widget, vedi Panoramica dei widget delle app.

Componenti del widget

Per creare un widget, devi disporre dei seguenti componenti di base:

Oggetto AppWidgetProviderInfo
Descrive i metadati di un widget, ad esempio il layout, la frequenza di aggiornamento e la classe AppWidgetProvider. AppWidgetProviderInfo è definito in XML, come descritto in questo documento.
AppWidgetProvider
Definisce i metodi di base che consentono di interagire a livello di programmazione con il widget. Tramite questo intent, ricevi trasmissioni quando il widget viene aggiornato, attivato, disattivato o eliminato. Dichiara AppWidgetProvider nel manifest e poi implementalo, come descritto in questo documento.
Visualizza layout
Definisce il layout iniziale del widget. Il layout è definito in XML, come descritto in questo documento.

La Figura 2 mostra come questi componenti si inseriscono nel flusso complessivo di elaborazione dei widget dell'app.

Flusso di elaborazione dei widget delle app
Figura 2. Flusso di elaborazione dei widget delle app.

Se il widget richiede la configurazione dell'utente, implementa l'attività di configurazione del widget dell'app. Questa attività consente agli utenti di modificare le impostazioni dei widget, ad esempio il fuso orario per un widget orologio.

Consigliamo anche i seguenti miglioramenti: layout flessibili dei widget, miglioramenti vari, widget avanzati, widget di raccolta e creazione di un host di widget.

Dichiarare il file XML AppWidgetProviderInfo

L'oggetto AppWidgetProviderInfo definisce le qualità essenziali di un widget. Definisci l'oggetto AppWidgetProviderInfo in un file di risorse XML utilizzando un singolo elemento <appwidget-provider> e salvalo nella cartella res/xml/ del progetto.

Ciò è mostrato nel seguente esempio:

<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>

Attributi di dimensionamento dei widget

Per impostazione predefinita, i widget vengono posizionati nella finestra della schermata Home in base a una griglia di celle con altezza e larghezza definite. La maggior parte delle schermate Home consente ai widget di assumere dimensioni che sono multipli interi delle celle della griglia, ad esempio due celle in orizzontale per tre celle in verticale.

Gli attributi di dimensionamento dei widget ti consentono di specificare una dimensione predefinita per il widget e di fornire limiti inferiori e superiori per la dimensione del widget. In questo contesto, le dimensioni predefinite di un widget sono quelle che assume quando viene aggiunto per la prima volta alla schermata Home.

La tabella seguente descrive gli attributi <appwidget-provider> relativi al dimensionamento dei widget:

Attributi e descrizione
targetCellWidth e targetCellHeight (Android 12), minWidth e minHeight
  • A partire da Android 12, gli attributi targetCellWidth e targetCellHeight specificano le dimensioni predefinite del widget in termini di celle della griglia. Questi attributi vengono ignorati in Android 11 e versioni precedenti e possono essere ignorati se la schermata Home non supporta un layout basato su griglia.
  • Gli attributi minWidth e minHeight specificano le dimensioni predefinite del widget in dp. Se i valori della larghezza o dell'altezza minima di un widget non corrispondono alle dimensioni delle celle, i valori vengono arrotondati per eccesso alla dimensione della cella più vicina.
Ti consigliamo di specificare entrambi i set di attributi: targetCellWidth e targetCellHeight, e minWidth e minHeight, in modo che la tua app possa utilizzare minWidth e minHeight se il dispositivo dell'utente non supporta targetCellWidth e targetCellHeight. Se supportati, gli attributi targetCellWidth e targetCellHeight hanno la precedenza sugli attributi minWidth e minHeight.
minResizeWidth e minResizeHeight Specifica le dimensioni minime assolute del widget. Questi valori specificano le dimensioni al di sotto delle quali il widget è illeggibile o inutilizzabile. L'utilizzo di questi attributi consente all'utente di ridimensionare il widget a una dimensione inferiore rispetto alla dimensione predefinita. L'attributo minResizeWidth viene ignorato se è maggiore di minWidth o se il ridimensionamento orizzontale non è abilitato. Vedi resizeMode. Allo stesso modo, l'attributo minResizeHeight viene ignorato se è maggiore di minHeight o se il ridimensionamento verticale non è abilitato.
maxResizeWidth e maxResizeHeight Specifica le dimensioni massime consigliate del widget. Se i valori non sono un multiplo delle dimensioni della cella della griglia, vengono arrotondati per eccesso alla dimensione della cella più vicina. L'attributo maxResizeWidth viene ignorato se è inferiore a minWidth o se il ridimensionamento orizzontale non è abilitato. Vedi resizeMode. Allo stesso modo, l'attributo maxResizeHeight viene ignorato se è maggiore di minHeight o se il ridimensionamento verticale non è abilitato. Introdotta in Android 12.
resizeMode Specifica le regole in base alle quali è possibile ridimensionare un widget. Puoi utilizzare questo attributo per rendere i widget della schermata Home ridimensionabili orizzontalmente, verticalmente o su entrambi gli assi. Gli utenti toccano e tengono premuto un widget per visualizzare i relativi punti di manipolazione per il ridimensionamento, quindi trascinano i punti di manipolazione orizzontali o verticali per modificarne le dimensioni nella griglia del layout. I valori dell'attributo resizeMode includono horizontal, vertical e none. Per dichiarare un widget ridimensionabile orizzontalmente e verticalmente, utilizza horizontal|vertical.

Esempio

Per illustrare in che modo gli attributi nella tabella precedente influiscono sul dimensionamento dei widget, supponiamo le seguenti specifiche:

  • Una cella della griglia è larga 30 dp e alta 50 dp.
  • Viene fornita la seguente specifica dell'attributo:
<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 partire da Android 12:

Utilizza gli attributi targetCellWidth e targetCellHeight come dimensioni predefinite del widget.

Le dimensioni predefinite del widget sono 2x2. Il widget può essere ridimensionato fino a 2x1 o fino a 4x3.

Android 11 e versioni precedenti:

Utilizza gli attributi minWidth e minHeight per calcolare la dimensione predefinita del widget.

La larghezza predefinita = Math.ceil(80 / 30) = 3

L'altezza predefinita = Math.ceil(80 / 50) = 2

Le dimensioni predefinite del widget sono 3x2. Il widget può essere ridimensionato fino a 2x1 o fino a schermo intero.

Attributi aggiuntivi del widget

La seguente tabella descrive gli attributi <appwidget-provider> relativi a qualità diverse dal dimensionamento dei widget.

Attributi e descrizione
updatePeriodMillis Definisce la frequenza con cui il framework dei widget richiede un aggiornamento da AppWidgetProvider chiamando il metodo di callback onUpdate(). Non è garantito che l'aggiornamento effettivo avvenga esattamente in tempo con questo valore e ti consigliamo di eseguire gli aggiornamenti il meno frequentemente possibile, non più di una volta all'ora, per risparmiare batteria. Per l'elenco completo delle considerazioni da fare per scegliere un periodo di aggiornamento appropriato, consulta Ottimizzazioni per l'aggiornamento dei contenuti dei widget.
initialLayout Punta alla risorsa di layout che definisce il layout del widget.
configure Definisce l'attività che viene avviata quando l'utente aggiunge il widget, consentendogli di configurare le proprietà del widget. Consulta Consentire agli utenti di configurare i widget. A partire da Android 12, la tua app può saltare la configurazione iniziale. Per maggiori dettagli, vedi Utilizzare la configurazione predefinita del widget.
description Specifica la descrizione del selettore di widget da visualizzare per il tuo widget. Introdotta in Android 12.
previewLayout (Android 12) e previewImage (Android 11 e versioni precedenti)
  • A partire da Android 12, l'attributo previewLayout specifica un'anteprima scalabile, che fornisci come layout XML impostato sulle dimensioni predefinite del widget. Idealmente, il file XML del layout specificato come questo attributo è lo stesso del widget effettivo con valori predefiniti realistici.
  • In Android 11 o versioni precedenti, l'attributo previewImage specifica un'anteprima dell'aspetto del widget dopo la configurazione, che l'utente vede quando seleziona il widget dell'app. Se non fornita, l'utente vede invece l'icona in Avvio applicazioni della tua app. Questo campo corrisponde all'attributo android:previewImage nell'elemento <receiver> del file AndroidManifest.xml.
Nota:ti consigliamo di specificare sia l'attributo previewImage sia l'attributo previewLayout in modo che la tua app possa ripiegare sull'utilizzo di previewImage se il dispositivo dell'utente non supporta previewLayout. Per maggiori dettagli, vedi Compatibilità con le versioni precedenti con anteprime scalabili dei widget.
autoAdvanceViewId Specifica l'ID visualizzazione della sottovista del widget che viene avanzata automaticamente dall'host del widget.
widgetCategory Dichiara se il widget può essere visualizzato nella schermata Home (home_screen), nella schermata di blocco (keyguard) o in entrambe. Per Android 5.0 e versioni successive, è valido solo home_screen.
widgetFeatures Dichiara le funzionalità supportate dal widget. Ad esempio, se vuoi che il widget utilizzi la configurazione predefinita quando un utente lo aggiunge, specifica sia il flag configuration_optional sia il flag reconfigurable. In questo modo, l'attività di configurazione non viene avviata dopo che un utente aggiunge il widget. L'utente può comunque riconfigurare il widget in un secondo momento.

Utilizzare la classe AppWidgetProvider per gestire le trasmissioni dei widget

La classe AppWidgetProvider gestisce le trasmissioni dei widget e aggiorna il widget in risposta agli eventi del ciclo di vita del widget. Le sezioni seguenti descrivono come dichiarare AppWidgetProvider nel manifest e quindi implementarlo.

Dichiarare un widget nel manifest

Innanzitutto, dichiara la classe AppWidgetProvider nel file AndroidManifest.xml della tua app, come mostrato nell'esempio seguente:

<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>

L'elemento <receiver> richiede l'attributo android:name, che specifica il AppWidgetProvider utilizzato dal widget. Il componente non deve essere esportato a meno che un processo separato non debba trasmettere al tuo AppWidgetProvider, il che di solito non accade.

L'elemento <intent-filter> deve includere un elemento <action> con l'attributo android:name. Questo attributo specifica che AppWidgetProvider accetta la trasmissione ACTION_APPWIDGET_UPDATE. Si tratta dell'unico broadcast che devi dichiarare esplicitamente. Il AppWidgetManager invia automaticamente tutte le altre trasmissioni dei widget a AppWidgetProvider come necessario.

L'elemento <meta-data> specifica la risorsa AppWidgetProviderInfo e richiede i seguenti attributi:

  • android:name: specifica il nome dei metadati. Utilizza android.appwidget.provider per identificare i dati come descrittore AppWidgetProviderInfo.
  • android:resource: specifica la posizione della risorsa AppWidgetProviderInfo.

Implementa la classe AppWidgetProvider

La classe AppWidgetProvider estende BroadcastReceiver come classe di utilità per gestire le trasmissioni dei widget. Riceve solo le trasmissioni di eventi pertinenti al widget, ad esempio quando il widget viene aggiornato, eliminato, attivato e disattivato. Quando si verificano questi eventi di trasmissione, vengono chiamati i seguenti metodi AppWidgetProvider:

onUpdate()
Viene chiamato per aggiornare il widget a intervalli definiti dall'attributo updatePeriodMillis in AppWidgetProviderInfo. Per ulteriori informazioni, consulta la tabella che descrive gli attributi aggiuntivi dei widget in questa pagina.
Questo metodo viene chiamato anche quando l'utente aggiunge il widget, quindi esegue la configurazione essenziale, ad esempio la definizione dei gestori di eventi per oggetti View o l'avvio di job per caricare i dati da visualizzare nel widget. Tuttavia, se dichiari un'attività di configurazione senza il flag configuration_optional, questo metodo non viene chiamato quando l'utente aggiunge il widget, ma viene chiamato per gli aggiornamenti successivi. È responsabilità dell'attività di configurazione eseguire il primo aggiornamento al termine della configurazione. Per ulteriori informazioni, consulta Consentire agli utenti di configurare i widget delle app.
Il callback più importante è onUpdate(). Per ulteriori informazioni, consulta la sezione Gestire gli eventi con la classe onUpdate() in questa pagina.
onAppWidgetOptionsChanged()

Viene chiamato quando il widget viene posizionato per la prima volta e ogni volta che viene ridimensionato. Utilizza questo callback per mostrare o nascondere i contenuti in base agli intervalli di dimensioni del widget. Ottieni gli intervalli di dimensioni e, a partire da Android 12, l'elenco delle dimensioni possibili che un'istanza del widget può assumere chiamando getAppWidgetOptions(), che restituisce un Bundle che include quanto segue:

onDeleted(Context, int[])

Viene chiamato ogni volta che un widget viene eliminato dall'host del widget.

onEnabled(Context)

Viene chiamato quando viene creata per la prima volta un'istanza del widget. Ad esempio, se l'utente aggiunge due istanze del widget, viene chiamato solo la prima volta. Se devi aprire un nuovo database o eseguire un'altra configurazione che deve essere eseguita una sola volta per tutte le istanze del widget, questo è il posto giusto per farlo.

onDisabled(Context)

Viene chiamato quando l'ultima istanza del widget viene eliminata dall'host del widget. Qui puoi eliminare il lavoro svolto in onEnabled(Context), ad esempio un database temporaneo.

onReceive(Context, Intent)

Viene chiamato per ogni trasmissione e prima di ciascuno dei metodi di callback precedenti. In genere non è necessario implementare questo metodo, perché l'implementazione AppWidgetProvider predefinita filtra tutte le trasmissioni dei widget e chiama i metodi precedenti in modo appropriato.

Devi dichiarare l'implementazione della classe AppWidgetProvider come ricevitore di trasmissioni utilizzando l'elemento <receiver> nel AndroidManifest. Per saperne di più, consulta la sezione Dichiarare un widget nel manifest in questa pagina.

Gestire gli eventi con la classe onUpdate()

Il callback AppWidgetProvider più importante è onUpdate(), perché viene chiamato quando ogni widget viene aggiunto a un host, a meno che tu non utilizzi un'attività di configurazione senza il flag configuration_optional. Se il widget accetta eventi di interazione dell'utente, registra i gestori di eventi in questo callback. Se il widget non crea file o database temporanei o non esegue altre operazioni che richiedono una pulizia, allora onUpdate() potrebbe essere l'unico metodo di callback che devi definire.

Ad esempio, se vuoi un widget con un pulsante che avvia un'attività quando viene toccato, puoi utilizzare la seguente implementazione di 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);
        }
    }
}

Questo AppWidgetProvider definisce solo il metodo onUpdate(), utilizzandolo per creare un PendingIntent che avvia un Activity e lo collega al pulsante del widget utilizzando setOnClickPendingIntent(int, PendingIntent). Include un ciclo che scorre ogni voce in appWidgetIds, che è un array di ID che identificano ogni widget creato da questo fornitore. Se l'utente crea più di un'istanza del widget, tutte si aggiornano contemporaneamente. Tuttavia, viene gestita una sola pianificazione updatePeriodMillis per tutte le istanze del widget. Ad esempio, se la pianificazione degli aggiornamenti è definita ogni due ore e viene aggiunta una seconda istanza del widget un'ora dopo la prima, entrambe vengono aggiornate nel periodo definito dalla prima e il secondo periodo di aggiornamento viene ignorato. Entrambi vengono aggiornati ogni due ore, non ogni ora.

Per ulteriori dettagli, consulta la classe di esempio ExampleAppWidgetProvider.java.

Ricevere intent di trasmissione dei widget

AppWidgetProvider è una classe di convenienza. Se vuoi ricevere le trasmissioni dei widget direttamente, puoi implementare il tuo BroadcastReceiver o eseguire l'override del callback onReceive(Context,Intent). Gli intent che devi considerare sono i seguenti:

Crea il layout del widget

Devi definire un layout iniziale per il widget in XML e salvarlo nella directory res/layout/ del progetto. Per ulteriori dettagli, consulta le linee guida di progettazione.

Creare il layout del widget è semplice se hai familiarità con i layout. Tuttavia, tieni presente che i layout dei widget si basano su RemoteViews, che non supporta tutti i tipi di widget di layout o visualizzazione. Non puoi utilizzare viste personalizzate o sottoclassi delle viste supportate da RemoteViews.

RemoteViews supporta anche ViewStub, che è un View invisibile di dimensioni zero che puoi utilizzare per gonfiare in modo differito le risorse di layout in fase di runtime.

Supporto per il comportamento stateful

Android 12 aggiunge il supporto del comportamento stateful utilizzando i seguenti componenti esistenti:

Il widget è ancora stateless. L'app deve memorizzare lo stato e registrarsi per gli eventi di modifica dello stato.

Esempio di widget della lista della spesa che mostra un comportamento stateful
Figura 3. Esempio di comportamento stateful.

Il seguente esempio di codice mostra come implementare questi componenti.

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));

Fornisci due layout: uno destinato ai dispositivi con Android 12 o versioni successive in res/layout-v31 e l'altro destinato alle versioni precedenti di Android 11 o precedenti nella cartella res/layout predefinita.

Implementare angoli arrotondati

Android 12 introduce i seguenti parametri di sistema per impostare i raggi degli angoli arrotondati del widget:

  • system_app_widget_background_radius: il raggio dell'angolo dello sfondo del widget, che non è mai superiore a 28 dp.

  • Raggio interno, che può essere calcolato dal raggio esterno e dal padding. Vedi lo snippet seguente:

    /**
     * Applies corner radius for views that are visually positioned [widgetPadding]dp inside of the
     * widget background.
     */
    @Composable
    fun GlanceModifier.appWidgetInnerCornerRadius(widgetPadding: Dp): GlanceModifier {
    
        if (Build.VERSION.SDK_INT < 31) {
            return this
        }
    
        val resources = LocalContext.current.resources
        // get dimension in float (without rounding).
        val px = resources.getDimension(android.R.dimen.system_app_widget_background_radius)
        val widgetBackgroundRadiusDpValue = px / resources.displayMetrics.density
        if (widgetBackgroundRadiusDpValue < widgetPadding.value) {
            return this
        }
        return this.cornerRadius(Dp(widgetBackgroundRadiusDpValue - widgetPadding.value))
    }

Per calcolare un raggio adatto per i contenuti interni del widget, utilizza la seguente formula: systemRadiusValue - widgetPadding

I widget che ritagliano i contenuti in forme non rettangolari devono utilizzare @android:id/background come ID visualizzazione della visualizzazione di sfondo con android:clipToOutline impostato su true.

Considerazioni importanti per gli angoli arrotondati

  • I launcher di terze parti e i produttori di dispositivi possono ignorare il parametro system_app_widget_background_radius in modo che sia inferiore a 28 dp.
  • Se il widget non utilizza @android:id/background o non definisce uno sfondo che ritaglia i contenuti in base al contorno, con android:clipToOutline impostato su true, il launcher identifica automaticamente lo sfondo e ritaglia il widget utilizzando un rettangolo con angoli arrotondati impostati sul raggio del sistema.

  • Le forme non rettangolari devono essere contenute all'interno del contenitore di ridimensionamento rettangolare arrotondato per non essere ritagliate.

  • A partire da Android 16, il valore di sistema AOSP per system_app_widget_background_radius è 24dp. I produttori di launcher e dispositivi possono ritagliare il widget in modo che si adatti a system_app_widget_background_radius.

  • Il contenuto interno di un widget deve avere un padding sufficiente per supportare valori del raggio fino a 28dp per evitare il ritaglio del contenuto da parte degli angoli arrotondati.system_app_widget_background_radius

Per la compatibilità dei widget con le versioni precedenti di Android, ti consigliamo di definire attributi personalizzati e utilizzare un tema personalizzato per eseguirne l'override per Android 12, come mostrato nei seguenti file XML di esempio:

/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" />