Esta página descreve os refinamentos no dimensionamento de widgets e a maior flexibilidade introduzidos no Android 12 (nível 31 da API). Também explicamos como determinar um tamanho para seu widget.
Usar APIs melhoradas para tamanhos e layouts de widgets
A partir do Android 12 (nível 31 da API), é possível fornecer atributos de tamanho mais refinados e layouts flexíveis fazendo o seguinte, conforme descrito nas seções a seguir:
Especifique outras restrições de dimensionamento de widgets.
Fornecer layouts responsivos ou layouts exatos.
Em versões anteriores do Android, era possível ver todos os tamanhos de um
widget usando os extras
OPTION_APPWIDGET_MIN_WIDTH
,
OPTION_APPWIDGET_MIN_HEIGHT
,
OPTION_APPWIDGET_MAX_WIDTH
e OPTION_APPWIDGET_MAX_HEIGHT
,
além de poder estimar o tamanho dele, mas essa lógica não funciona em todas
as situações. Para widgets destinados ao Android 12 ou mais recente, recomendamos
fornecer layouts responsivos ou layouts
exatos.
Especificar outras restrições de dimensionamento do widget
O Android 12 adiciona APIs para garantir que o widget seja dimensionado de forma mais confiável em diferentes dispositivos com diferentes tamanhos de tela.
Além dos atributos minWidth
,
minHeight
,
minResizeWidth
,
e minResizeHeight
,
use os novos atributos appwidget-provider
a seguir:
targetCellWidth
etargetCellHeight
: definem o tamanho de destino do widget em termos de células de grade na tela de início. Se definidos, esses atributos serão usados em vez deminWidth
ouminHeight
.maxResizeWidth
emaxResizeHeight
: definem o tamanho máximo que a tela de início permite que o usuário redimensione o widget.
O XML a seguir mostra como usar os atributos de dimensionamento.
<appwidget-provider
...
android:targetCellWidth="3"
android:targetCellHeight="2"
android:maxResizeWidth="250dp"
android:maxResizeHeight="110dp">
</appwidget-provider>
Fornecer layouts responsivos
Se o layout precisar mudar dependendo do tamanho do widget, recomendamos criar um pequeno conjunto de layouts, cada um válido para uma série de tamanhos. Se isso não for possível, outra opção é fornecer layouts com base no tamanho exato do widget durante a execução, conforme descrito nesta página.
Esse recurso melhora a escala e a integridade do sistema em geral. Isso ocorre porque o sistema não precisa ativar o app sempre que ele exibir o widget em um tamanho diferente.
O exemplo de código a seguir mostra como fornecer uma lista de layouts.
Kotlin
override fun onUpdate(...) { val smallView = ... val tallView = ... val wideView = ... val viewMapping: Map<SizeF, RemoteViews> = mapOf( SizeF(150f, 100f) to smallView, SizeF(150f, 200f) to tallView, SizeF(215f, 100f) to wideView ) val remoteViews = RemoteViews(viewMapping) appWidgetManager.updateAppWidget(id, remoteViews) }
Java
@Override public void onUpdate(...) { RemoteViews smallView = ...; RemoteViews tallView = ...; RemoteViews wideView = ...; Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); viewMapping.put(new SizeF(150f, 100f), smallView); viewMapping.put(new SizeF(150f, 200f), tallView); viewMapping.put(new SizeF(215f, 100f), wideView); RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews); }
Suponha que o widget tenha os seguintes atributos:
<appwidget-provider
android:minResizeWidth="160dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="250dp"
android:maxResizeHeight="200dp">
</appwidget-provider>
O snippet de código anterior significa o seguinte:
- O
smallView
é compatível com 160 dp (minResizeWidth
) × 110 dp (minResizeHeight
) a 160 dp × 199 dp (próximo ponto de corte - 1 dp). - O
tallView
é compatível com 160 dp × 200 dp a 214 dp (próximo ponto de corte - 1) × 200 dp. O
wideView
aceita de 215 dp × 110 dp (minResizeHeight
) a 250 dp (maxResizeWidth
) × 200 dp (maxResizeHeight
).
Seu widget precisa ser compatível com o intervalo de tamanho de minResizeWidth
× minResizeHeight
a maxResizeWidth
× maxResizeHeight
. Dentro desse intervalo, você pode decidir o ponto de corte para mudar os layouts.

Fornecer layouts exatos
Se não for viável usar um pequeno conjunto de layouts responsivos, é possível fornecer layouts diferentes de acordo com os tamanhos de exibição do widget. Normalmente, há dois tamanhos para smartphones (modo retrato e paisagem) e quatro para dispositivos dobráveis.
Para implementar essa solução, o app precisa realizar as seguintes etapas:
Sobrecarregue
AppWidgetProvider.onAppWidgetOptionsChanged()
, que é chamado quando o conjunto de tamanhos muda.Chame
AppWidgetManager.getAppWidgetOptions()
, que retorna umBundle
contendo os tamanhos.Acesse a chave
AppWidgetManager.OPTION_APPWIDGET_SIZES
doBundle
.
O exemplo de código a seguir mostra como fornecer layouts exatos.
Kotlin
override fun onAppWidgetOptionsChanged( context: Context, appWidgetManager: AppWidgetManager, id: Int, newOptions: Bundle? ) { super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions) // Get the new sizes. val sizes = newOptions?.getParcelableArrayList<SizeF>( AppWidgetManager.OPTION_APPWIDGET_SIZES ) // Check that the list of sizes is provided by the launcher. if (sizes.isNullOrEmpty()) { return } // Map the sizes to the RemoteViews that you want. val remoteViews = RemoteViews(sizes.associateWith(::createRemoteViews)) appWidgetManager.updateAppWidget(id, remoteViews) } // Create the RemoteViews for the given size. private fun createRemoteViews(size: SizeF): RemoteViews { }
Java
@Override public void onAppWidgetOptionsChanged( Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); // Get the new sizes. ArrayList<SizeF> sizes = newOptions.getParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES); // Check that the list of sizes is provided by the launcher. if (sizes == null || sizes.isEmpty()) { return; } // Map the sizes to the RemoteViews that you want. Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); for (SizeF size : sizes) { viewMapping.put(size, createRemoteViews(size)); } RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews); } // Create the RemoteViews for the given size. private RemoteViews createRemoteViews(SizeF size) { }
Determinar um tamanho para seu widget
Cada widget precisa definir um targetCellWidth
e targetCellHeight
para dispositivos
com Android 12 ou versões mais recentes ou minWidth
e minHeight
para todas as
versões do Android, indicando a quantidade mínima de espaço que ele consome
por padrão. No entanto, quando os usuários adicionam um widget à tela inicial, ele geralmente ocupa mais que a largura e a altura mínimas especificadas.
As telas iniciais do Android oferecem aos usuários uma grade de espaços disponíveis em que eles podem colocar widgets e ícones. Essa grade pode variar de acordo com o dispositivo. Por exemplo, muitos
smartphones oferecem uma grade de 5x4, e os tablets podem oferecer uma grade maior. Quando o widget
é adicionado, ele é esticado para ocupar o número mínimo de células,
horizontal e verticalmente, necessário para satisfazer as restrições de
targetCellWidth
e targetCellHeight
em dispositivos com
Android 12 ou mais recente, ou restrições de minWidth
e minHeight
em
dispositivos com Android 11 (nível 30 da API) ou versões anteriores.
A largura e a altura de uma célula, assim como o tamanho das margens automáticas aplicadas aos widgets, podem variar entre os dispositivos. Use a tabela a seguir para estimar as dimensões mínimas do widget em um smartphone típico com grade 5x4, de acordo com o número de células ocupadas que você quer:
Número de células (largura x altura) | Tamanho disponível no modo retrato (dp) | Tamanho disponível no modo paisagem (dp) |
---|---|---|
1x1 | 57x102dp | 127x51dp |
2x1 | 130x102dp | 269x51dp |
3x1 | 203x102dp | 412x51dp |
4x1 | 276x102dp | 554x51dp |
5x1 | 349x102dp | 697x51dp |
5x2 | 349x220dp | 697x117dp |
5x3 | 349x337dp | 697x184dp |
5x4 | 349x455dp | 697x250dp |
… | … | … |
n x m | (73n - 16) x (118m - 16) | (142n - 15) x (66m - 15) |
Use os tamanhos de célula do modo retrato para informar os valores que você fornece para os atributos minWidth
, minResizeWidth
e maxResizeWidth
. Da mesma forma, use os tamanhos de célula do modo paisagem para informar os valores fornecidos para os atributos minHeight
, minResizeHeight
e maxResizeHeight
.
Isso acontece porque a largura da célula geralmente é menor no modo retrato do que no modo paisagem. Da mesma forma, a altura da célula geralmente é menor no modo paisagem do que no modo retrato.
Por exemplo, se você quiser que a largura do widget seja redimensionável até uma célula em um Google Pixel 4, defina o minResizeWidth
como no máximo 56 dp para garantir que o valor do atributo minResizeWidth
seja menor que 57 dp, já que uma célula tem pelo menos 57 dp de largura no modo retrato.
Da mesma forma, se você quiser que a altura do widget seja redimensionável em uma célula no mesmo dispositivo, defina o minResizeHeight
como no máximo 50 dp para garantir que o valor do atributo minResizeHeight
seja menor que 51 dp, já que uma célula tem pelo menos 51 dp de altura no modo paisagem.
Cada widget é redimensionável dentro dos intervalos de tamanho entre os atributos
minResizeWidth
/minResizeHeight
e maxResizeWidth
/maxResizeHeight
, o que significa que ele precisa se adaptar a qualquer intervalo de tamanho entre eles.
Por exemplo, para definir o tamanho padrão do widget no posicionamento, você pode definir os seguintes atributos:
<appwidget-provider
android:targetCellWidth="3"
android:targetCellHeight="2"
android:minWidth="180dp"
android:minHeight="110dp">
</appwidget-provider>
Isso significa que o tamanho padrão do widget é de 3x2 células, conforme especificado pelos atributos
targetCellWidth
e targetCellHeight
, ou 180×110 dp, conforme
especificado por minWidth
e minHeight
para dispositivos com
Android 11 ou versões anteriores. Nesse caso, o tamanho em células pode variar dependendo do dispositivo.
Além disso, para definir os intervalos de tamanho compatíveis do widget, você pode definir os seguintes atributos:
<appwidget-provider
android:minResizeWidth="180dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="530dp"
android:maxResizeHeight="450dp">
</appwidget-provider>
Conforme especificado pelos atributos anteriores, a largura do widget pode ser redimensionada de 180 dp para 530 dp, e a altura pode ser redimensionada de 110 dp para 450 dp. O widget pode ser redimensionado de células 3x2 para 5x2, desde que as seguintes condições estejam presentes:
- O dispositivo tem a grade 5x4.
- O mapeamento entre o número de células e o tamanho disponível em dps segue a tabela que mostra a estimativa das dimensões mínimas nesta página.
- O widget se adapta a esse intervalo de tamanho.
Kotlin
val smallView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_small) val mediumView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_medium) val largeView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_large) val viewMapping: Map<SizeF, RemoteViews> = mapOf( SizeF(180f, 110f) to smallView, SizeF(270f, 110f) to mediumView, SizeF(270f, 280f) to largeView ) appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(viewMapping))
Java
RemoteViews smallView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_small); RemoteViews mediumView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_medium); RemoteViews largeView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_large); Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); viewMapping.put(new SizeF(180f, 110f), smallView); viewMapping.put(new SizeF(270f, 110f), mediumView); viewMapping.put(new SizeF(270f, 280f), largeView); RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews);
Suponha que o widget use os layouts responsivos definidos nos snippets de código anteriores. Isso significa que o layout especificado como
R.layout.widget_weather_forecast_small
é usado de 180 dp (minResizeWidth
) x
110 dp (minResizeHeight
) a 269 x 279 dp (próximos pontos de corte - 1). Da mesma forma, R.layout.widget_weather_forecast_medium
é usado de 270x110dp a 270x279dp, e R.layout.widget_weather_forecast_large
é usado de 270x280dp a 530dp (maxResizeWidth
) x 450dp (maxResizeHeight
).
À medida que o usuário redimensiona o widget, a aparência dele muda para se adaptar a cada tamanho em células, conforme mostrado nos exemplos a seguir.

R.layout.widget_weather_forecast_small
.
R.layout.widget_weather_forecast_medium
.
R.layout.widget_weather_forecast_medium
.
R.layout.widget_weather_forecast_large
.
R.layout.widget_weather_forecast_large
.