Criar um widget de app com o Glance

As seções a seguir descrevem como criar um widget de app simples com o Glance.

Declarar AppWidget no manifesto

Depois de concluir as etapas de configuração, declare o AppWidget e os metadados em seu app.

  1. Registrar o provedor do widget de app no seu arquivo AndroidManifest.xml e o arquivo de metadados associado:
<receiver android:name=".glance.MyReceiver"
    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/my_app_widget_info" />
</receiver>
  1. Estenda o receptor AppWidget do GlanceAppWidgetReceiver:

class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
    override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget")
}

Adicione os metadados AppWidgetProviderInfo.

Em seguida, siga esta etapa para adicionar os metadados AppWidgetProviderInfo:

  1. Siga o guia Criar um widget simples para criar e definir o app informações do widget no arquivo @xml/my_app_widget_info.

    A única diferença para o Glance é que não há XML initialLayout, mas é preciso definir um. É possível usar o layout de carregamento predefinido fornecido no biblioteca:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>

Definir GlanceAppWidget

  1. Crie uma nova classe que se estenda do GlanceAppWidget e modifique a provideGlance. Esse é o método em que você carrega dados necessárias para renderizar o widget:

class MyAppWidget : GlanceAppWidget() {

    override suspend fun provideGlance(context: Context, id: GlanceId) {

        // In this method, load data needed to render the AppWidget.
        // Use `withContext` to switch to another thread for long running
        // operations.

        provideContent {
            // create your AppWidget here
            Text("Hello World")
        }
    }
}

  1. Instancie-o no glanceAppWidget no seu GlanceAppWidgetReceiver:

class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {

    // Let MyAppWidgetReceiver know which GlanceAppWidget to use
    override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
}

Você configurou um AppWidget usando o Glance.

Criar interface

O snippet abaixo demonstra como criar a interface:

/* Import Glance Composables
 In the event there is a name clash with the Compose classes of the same name,
 you may rename the imports per https://kotlinlang.org/docs/packages.html#imports
 using the `as` keyword.

import androidx.glance.Button
import androidx.glance.layout.Column
import androidx.glance.layout.Row
import androidx.glance.text.Text
*/
class MyAppWidget : GlanceAppWidget() {

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // Load data needed to render the AppWidget.
        // Use `withContext` to switch to another thread for long running
        // operations.

        provideContent {
            // create your AppWidget here
            GlanceTheme {
                MyContent()
            }
        }
    }

    @Composable
    private fun MyContent() {
        Column(
            modifier = GlanceModifier.fillMaxSize()
                .background(GlanceTheme.colors.background),
            verticalAlignment = Alignment.Top,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp))
            Row(horizontalAlignment = Alignment.CenterHorizontally) {
                Button(
                    text = "Home",
                    onClick = actionStartActivity<MyActivity>()
                )
                Button(
                    text = "Work",
                    onClick = actionStartActivity<MyActivity>()
                )
            }
        }
    }
}

O exemplo de código anterior faz o seguinte:

  • No nível superior Column, os itens são colocados verticalmente um após cada entre si.
  • O Column expande o próprio tamanho para corresponder ao espaço disponível (usando o GlanceModifier e alinha o conteúdo dele ao topo (verticalAlignment) e a centraliza horizontalmente (horizontalAlignment).
  • O conteúdo do Column é definido usando a lambda. A ordem é importante.
    • O primeiro item no Column é um componente Text com 12.dp de padding.
    • O segundo item é uma Row, em que os itens são colocados um na horizontal. um após o outro, com dois Buttons centralizados horizontalmente (horizontalAlignment). A exibição final depende do espaço disponível. A imagem a seguir é um exemplo de como ele pode ficar:
widget_de_destino
Figura 1. Exemplo de interface.

É possível mudar os valores de alinhamento ou aplicar diferentes valores de modificador (como padding) para alterar a posição e o tamanho dos componentes. Consulte a referência Documentação para obter uma lista completa de componentes, parâmetros e modificadores para cada classe.