Adicionar prévias geradas ao seletor de widgets

Com as visualizações geradas, você cria visualizações dinâmicas e personalizadas para seus widgets que refletem com precisão como eles vão aparecer na tela inicial de um usuário. Elas são fornecidas por uma API push, o que significa que seu app fornece a prévia a qualquer momento durante o ciclo de vida sem receber uma solicitação explícita do host do widget.

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

Para mais informações, assista Enriqueça seu app com atualizações em tempo real e widgets no YouTube.

Configurar o app para visualizações de widgets gerados

Para mostrar as visualizações de widgets gerados em um dispositivo 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 GlanceAppWidgetManager ou AppWidgetManager. Para evitar abusos e reduzir problemas de integridade do sistema, a API setWidgetPreview tem limite de taxa. O limite padrão é de aproximadamente duas chamadas por hora.

Gerar uma visualização atualizada com o Jetpack Glance

Para widgets criados com o Jetpack Glance, faça o seguinte:

  1. Substitua a função GlanceAppWidget.providePreview para fornecer o conteúdo combinável para a prévia. Como faria em provideGlance, carregue os dados do app e transmita-os ao elemento combinável de conteúdo do widget para garantir que a prévia mostre dados precisos. Ao contrário de provideGlance, essa é uma única composição sem recomposição ou efeitos.

  2. Chame GlanceAppWidgetManager.setWidgetPreviews para gerar e publicar a prévia.

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.
  • Você pode definir a prévia depois que o app tiver dados, por exemplo, após o login de um usuário ou a configuração inicial.
  • É possível configurar uma tarefa periódica para atualizar as prévias na cadência escolhida.

Solução de problemas com prévias geradas

Um problema comum é que, depois de gerar uma prévia, imagens, ícones ou outros combináveis podem estar faltando na imagem de prévia, em relação ao tamanho de soltar do widget. Esse tamanho de redução é definido por targetCellWidth e targetCellHeight, se especificado, ou por minWidth e minHeight no arquivo de informações do provedor de widget de app.

Isso ocorre porque o Android, por padrão, renderiza apenas elementos combináveis visíveis no tamanho mínimo do widget. Em outras palavras, o Android define previewSizeMode como SizeMode.Single por padrão. Ele usa android:minHeight e android:minWidth no XML de informações do provedor de widget de app para determinar quais elementos combináveis desenhar.

Para corrigir isso, substitua previewSizeMode no GlanceAppWidget e defina como SizeMode.Responsive, fornecendo um conjunto de valores DpSize. Isso informa ao Android todos os tamanhos de layout necessários para renderizar a prévia, garantindo que todos os elementos sejam exibidos corretamente.

Otimize para formatos específicos. Forneça um ou dois tamanhos começando pelo mínimo e seguindo os pontos de interrupção do widget. Especifique pelo menos uma imagem para compatibilidade com versões anteriores. Consulte os valores mínimos de DP adequados para diferentes tamanhos de grade nas diretrizes de design de widgets.

Gerar uma prévia atualizada sem o Jetpack Glance

Você pode usar o RemoteViews sem o recurso Em um relance. 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 visualizações de widgets escalonáveis ao seletor

A partir do Android 12, a visualização do widget exibida no seletor de widgets é escalonável. Você o fornece como um layout XML definido para o tamanho padrão do widget. Antes, a visualização do widget era um recurso drawable estático, em alguns casos, a visualização não refletia corretamente a aparência dos widgets quando eram adicionados à tela inicial.

Para implementar visualizações 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 o mesmo previewLayout e initialLayout. Para orientações sobre como criar layouts de prévia precisos, consulte a seção a seguir nesta página.

Recomendamos especificar os atributos previewLayout e previewImage para que seu 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.

Compatibilidade com versões anteriores usando visualizações de widgets

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 um substituto para prévias geradas, especifique o atributo previewImage.

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

Criar prévias precisas que incluam itens dinâmicos

Figura 1 : uma prévia de widget sem itens de lista.

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

Se o widget usar uma dessas visualizações, criar uma prévia escalonável fornecendo diretamente o layout do widget vai prejudicar a experiência quando a prévia não mostrar itens. Isso acontece porque os dados da visualização de coleção são definidos dinamicamente durante a execução, e ela se parece com a imagem mostrada na figura 1.

Para que as prévias dos 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 falsos de lista.

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 em tempo de execução.

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

Itens de lista complexos

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

Considere um item de lista definido em widget_list_item.xml e composto por 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, inclua o layout várias vezes, mas isso faz com que cada item 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 prévia. 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 prévia:

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