Adicionar prévias ao seletor de widgets

Para melhorar a experiência do seletor de widgets do seu app, forneça uma prévia de widget gerada em dispositivos com o Android 15 e versões mais recentes, uma prévia de widget dimensionada (especificando um previewLayout) para dispositivos com o Android 12 ao Android 14 e um previewImage para versões anteriores.

As prévias geradas de widgets permitem criar prévias dinâmicas e personalizadas para seus widgets que refletem com precisão como eles vão aparecer na tela inicial do usuário. No Android 15 e versões mais recentes, elas são fornecidas por uma API push, o que significa que o app fornece a prévia em qualquer momento do ciclo de vida sem receber uma solicitação explícita do host do widget.

Para mais informações, assista Enrich your app with atualizações em tempo real and widgets no YouTube.

Adicionar prévias geradas

Para mostrar as prévias de widgets geradas em um dispositivo com o Android 15 ou mais recente, primeiro defina o valor de compileSdk como 35 ou mais recente no arquivo build.gradle do módulo para ter a capacidade de fornecer RemoteViews ao seletor de widgets.

Os apps podem usar setWidgetPreview em AppWidgetManager. Para evitar abusos e mitigar problemas de integridade do sistema, a setWidgetPreview é uma API com limitação de taxa. O limite padrão é de aproximadamente duas chamadas por hora.

Não há um callback do sistema para fornecer prévias. Portanto, o app precisa decidir quando chamar setWidgetPreviews. A estratégia de atualização depende do caso de uso do widget:

  • Se o widget tiver informações estáticas ou for uma ação rápida, defina a prévia quando o app for iniciado pela primeira vez.
  • É possível definir a prévia quando o app tiver dados, por exemplo, após o login do usuário ou a configuração inicial.
  • É possível configurar uma tarefa periódica para atualizar as prévias em uma frequência escolhida.

O exemplo a seguir carrega um recurso de layout de widget XML e o define como a prévia. Uma configuração de build compileSdk de 35 ou mais recente é necessária para que setWidgetPreview apareça como um método neste snippet.

AppWidgetManager.getInstance(appContext).setWidgetPreview(
    ComponentName(
        appContext,
        ExampleAppWidgetReceiver::class.java
    ),
    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
    RemoteViews("com.example", R.layout.widget_preview)
)

Adicionar prévias de widgets escalonáveis

A partir do Android 12, a prévia do widget mostrada no seletor é escalonável. Ele é fornecido como um conjunto de layout XML para o tamanho padrão do widget. Antes, a prévia do widget era um recurso drawable estático, o que, em alguns casos, levava a prévias que não refletiam com precisão como os widgets apareciam quando eram adicionados à tela inicial.

Para implementar prévias de widgets escalonáveis, use o atributo previewLayout do elemento appwidget-provider para fornecer um layout XML:

<appwidget-provider
    android:previewLayout="@layout/my_widget_preview">
</appwidget-provider>

Recomendamos usar o mesmo layout do widget real, com valores padrão ou de teste realistas. A maioria dos apps usa os mesmos previewLayout e initialLayout. Para orientações sobre como criar layouts de visualização precisos, consulte Criar visualizações precisas que incluam itens dinâmicos.

Recomendamos especificar os atributos previewLayout e previewImage, para que o app possa usar previewImage se o dispositivo do usuário não for compatível com previewLayout. O atributo previewLayout tem precedência sobre o atributo previewImage.

Adicionar prévias de widgets estáticos para compatibilidade com versões anteriores

Para permitir que os seletores de widgets no Android 11 (nível 30 da API) ou versões anteriores mostrem prévias do seu widget ou como substituto para prévias escalonáveis, especifique o atributo previewImage.

Se você mudar a aparência do widget, atualize a imagem de visualização.

Esse atributo também é usado como substituto para prévias geradas se você não tiver definido uma usando setWidgetPreview.

Criar prévias precisas que incluam itens dinâmicos

Figura 1 : uma prévia do widget que não mostra itens de lista.

Nesta seção, explicamos a abordagem recomendada para mostrar vários itens em uma prévia de um widget com uma visualização de coleção, ou seja, um widget que usa um ListView, GridView ou StackView. Isso se aplica a prévias de widgets escalonáveis, não a prévias geradas.

Se o widget usar uma dessas visualizações, criar uma prévia escalonável fornecendo o layout real do widget diretamente em previewLayout pode prejudicar a experiência quando a prévia do widget não mostrar itens. Isso ocorre porque os dados da visualização de coleção são definidos dinamicamente no momento da execução e são semelhantes à imagem mostrada na Figura 1.

Para que as prévias de widgets com visualizações de coleção sejam mostradas corretamente no seletor de widgets, recomendamos manter um arquivo de layout separado designado apenas para a prévia. Esse arquivo de layout separado precisa incluir o seguinte:

  • O layout real do widget.
  • Uma visualização de coleção de marcador de posição com itens falsos. Por exemplo, é possível simular um ListView fornecendo um marcador de posição LinearLayout com vários itens de lista falsos.

Para ilustrar um exemplo de ListView, comece com um arquivo de layout separado:

// res/layout/widget_preview.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@drawable/widget_background"
   android:orientation="vertical">

    // Include the actual widget layout that contains ListView.
    <include
        layout="@layout/widget_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    // The number of fake items you include depends on the values you provide
    // for minHeight or targetCellHeight in the AppWidgetProviderInfo
    // definition.

    <TextView android:text="@string/fake_item1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

    <TextView android:text="@string/fake_item2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

</LinearLayout>

Especifique o arquivo de layout de visualização ao fornecer o atributo previewLayout dos metadados AppWidgetProviderInfo. Você ainda especifica o layout real do widget para o atributo initialLayout e usa o layout real do widget ao construir um RemoteViews no momento da execução.

<appwidget-provider
    previewLayout="@layout/widget_preview"
    initialLayout="@layout/widget_view" />

Itens de lista complexos

O exemplo na seção anterior fornece itens de lista falsos, porque os itens da lista são objetos TextView. Pode ser mais complexo fornecer itens falsos se eles forem layouts complexos.

Considere um item de lista definido em widget_list_item.xml e que consiste em dois objetos TextView:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView android:id="@id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_title" />

    <TextView android:id="@id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_content" />
</LinearLayout>

Para fornecer itens de lista falsos, você pode incluir o layout várias vezes, mas isso faz com que cada item de lista seja idêntico. Para fornecer itens de lista exclusivos, siga estas etapas:

  1. Crie um conjunto de atributos para os valores de texto:

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. Use estes atributos para definir o texto:

    <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
        <TextView android:id="@id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetTitle" />
    
        <TextView android:id="@id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetContent" />
    </LinearLayout>
    
  3. Crie quantos estilos forem necessários para a visualização. Redefina os valores em cada estilo:

    <resources>
    
        <style name="Theme.Widget.ListItem">
            <item name="widgetTitle"></item>
            <item name="widgetContent"></item>
        </style>
        <style name="Theme.Widget.ListItem.Preview1">
            <item name="widgetTitle">Fake Title 1</item>
            <item name="widgetContent">Fake content 1</item>
        </style>
        <style name="Theme.Widget.ListItem.Preview2">
            <item name="widgetTitle">Fake title 2</item>
            <item name="widgetContent">Fake content 2</item>
        </style>
    
    </resources>
    
  4. Aplique os estilos aos itens falsos no layout de visualização:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" ...>
    
        <include layout="@layout/widget_view" ... />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview1" />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview2" />
    
    </LinearLayout>