На этой странице описываются усовершенствования в области изменения размера виджетов и большая гибкость, появившиеся в Android 12 (API уровня 31). Здесь также подробно описывается, как определить размер виджета .
Используйте улучшенные API для размеров и макетов виджетов
Начиная с Android 12 (уровень API 31), вы можете предоставить более точные атрибуты размера и гибкие макеты, выполнив следующие действия, как описано в следующих разделах:
Предоставление адаптивных макетов или точных макетов.
В предыдущих версиях Android можно было получить диапазоны размеров виджета с помощью дополнительных параметров OPTION_APPWIDGET_MIN_WIDTH
, OPTION_APPWIDGET_MIN_HEIGHT
, OPTION_APPWIDGET_MAX_WIDTH
и OPTION_APPWIDGET_MAX_HEIGHT
, а затем оценить размер виджета, но эта логика работает не во всех случаях. Для виджетов, предназначенных для Android 12 и выше, мы рекомендуем предоставлять адаптивные или точные макеты .
Укажите дополнительные ограничения размера виджета
В Android 12 добавлены API, позволяющие более точно определять размер виджета на разных устройствах с разными размерами экрана.
В дополнение к существующим атрибутам minWidth
, minHeight
, minResizeWidth
и minResizeHeight
используйте следующие новые атрибуты appwidget-provider
:
targetCellWidth
иtargetCellHeight
: определяют целевой размер виджета относительно ячеек сетки панели запуска. Если они определены, эти атрибуты используются вместоminWidth
илиminHeight
.maxResizeWidth
иmaxResizeHeight
: определяют максимальный размер, до которого лаунчер позволяет пользователю изменять размер виджета.
Следующий XML-код показывает, как использовать атрибуты размера.
<appwidget-provider
...
android:targetCellWidth="3"
android:targetCellHeight="2"
android:maxResizeWidth="250dp"
android:maxResizeHeight="110dp">
</appwidget-provider>
Обеспечьте адаптивные макеты
Если макет должен меняться в зависимости от размера виджета, мы рекомендуем создать небольшой набор макетов, каждый из которых подходит для определённого диапазона размеров. Если это невозможно, можно использовать макеты, основанные на точном размере виджета во время выполнения , как описано на этой странице.
Эта функция обеспечивает более плавное масштабирование и общее улучшение работоспособности системы, поскольку системе не приходится каждый раз активировать приложение, когда она отображает виджет в другом размере.
В следующем примере кода показано, как предоставить список макетов.
Котлин
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) }
Ява
@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); }
Предположим, что виджет имеет следующие атрибуты:
<appwidget-provider
android:minResizeWidth="160dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="250dp"
android:maxResizeHeight="200dp">
</appwidget-provider>
Предыдущий фрагмент кода означает следующее:
-
smallView
поддерживает от 160dp (minResizeWidth
) × 110dp (minResizeHeight
) до 160dp × 199dp (следующая точка отсечения - 1dp). -
tallView
поддерживает от 160dp × 200dp до 214dp (следующая точка отсечения - 1) × 200dp. wideView
поддерживает от 215dp × 110dp (minResizeHeight
) до 250dp (maxResizeWidth
) × 200dp (maxResizeHeight
).
Ваш виджет должен поддерживать диапазон размеров от minResizeWidth
× minResizeHeight
до maxResizeWidth
× maxResizeHeight
. В этом диапазоне вы можете задать точку отсечения для переключения макетов.

Предоставьте точные макеты
Если небольшой набор адаптивных макетов невозможен, вы можете предоставить различные макеты, адаптированные к размерам, в которых отображается виджет. Обычно это два размера для телефонов (портретный и альбомный режимы) и четыре размера для складных устройств.
Чтобы реализовать это решение, вашему приложению необходимо выполнить следующие шаги:
Перегрузите
AppWidgetProvider.onAppWidgetOptionsChanged()
, который вызывается при изменении набора размеров.Вызовите
AppWidgetManager.getAppWidgetOptions()
, который возвращаетBundle
, содержащий размеры.Получите доступ к ключу
AppWidgetManager.OPTION_APPWIDGET_SIZES
изBundle
.
В следующем примере кода показано, как предоставить точные макеты.
Котлин
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 { }
Ява
@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) { }
Определите размер вашего виджета
Для каждого виджета должны быть заданы параметры targetCellWidth
и targetCellHeight
для устройств под управлением Android 12 и выше, а также minWidth
и minHeight
для всех версий Android, которые указывают минимальный размер занимаемого им пространства по умолчанию. Однако, когда пользователи добавляют виджет на главный экран, он, как правило, занимает больше указанного вами минимального размера ширины и высоты.
Домашние экраны Android предлагают пользователям сетку с доступными ячейками для размещения виджетов и значков. Эта сетка может различаться в зависимости от устройства; например, многие мобильные телефоны предлагают сетку 5x4, а планшеты могут иметь более крупную сетку. При добавлении виджета он растягивается, занимая минимальное количество ячеек по горизонтали и вертикали, необходимое для удовлетворения ограничений targetCellWidth
и targetCellHeight
на устройствах под управлением Android 12 и выше, или ограничений minWidth
и minHeight
на устройствах под управлением Android 11 (уровень API 30) и ниже.
Ширина и высота ячейки, а также размер автоматических полей, применяемых к виджетам, могут различаться на разных устройствах. Используйте следующую таблицу, чтобы приблизительно оценить минимальные размеры виджета для типичного мобильного устройства с сеткой 5x4, учитывая необходимое количество занятых ячеек сетки:
Количество ячеек (ширина x высота) | Доступный размер в портретном режиме (dp) | Доступный размер в альбомной ориентации (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 |
... | ... | ... |
нксм | (73н - 16) х (118м - 16) | (142н - 15) х (66м - 15) |
Используйте размеры ячеек в портретном режиме для задания значений атрибутов minWidth
, minResizeWidth
и maxResizeWidth
. Аналогично, используйте размеры ячеек в альбомном режиме для задания значений атрибутов minHeight
, minResizeHeight
и maxResizeHeight
.
Причина этого в том, что ширина ячейки в портретном режиме обычно меньше, чем в альбомном, и, аналогично, высота ячейки в альбомном режиме обычно меньше, чем в портретном.
Например, если вы хотите, чтобы ширина виджета изменялась до одной ячейки на Google Pixel 4, вам нужно установить значение minResizeWidth
не более 56 dp, чтобы значение атрибута minResizeWidth
было меньше 57 dp, поскольку ширина ячейки в портретной ориентации составляет не менее 57 dp. Аналогично, если вы хотите, чтобы высота виджета изменялась до одной ячейки на том же устройстве, вам нужно установить значение minResizeHeight
не более 50 dp, чтобы значение атрибута minResizeHeight
было меньше 51 dp, поскольку высота ячейки в альбомной ориентации составляет не менее 51 dp.
Размер каждого виджета можно изменять в пределах диапазонов между атрибутами minResizeWidth
/ minResizeHeight
и maxResizeWidth
/ maxResizeHeight
, что означает, что он должен адаптироваться к любым диапазонам размеров между ними.
Например, чтобы задать размер виджета по умолчанию при размещении, можно задать следующие атрибуты:
<appwidget-provider
android:targetCellWidth="3"
android:targetCellHeight="2"
android:minWidth="180dp"
android:minHeight="110dp">
</appwidget-provider>
Это означает, что размер виджета по умолчанию составляет 3x2 ячейки, как указано атрибутами targetCellWidth
и targetCellHeight
, или 180×110dp, как указано атрибутами minWidth
и minHeight
для устройств под управлением Android 11 и ниже. В последнем случае размер ячеек может различаться в зависимости от устройства.
Также, чтобы задать поддерживаемые диапазоны размеров вашего виджета, вы можете задать следующие атрибуты:
<appwidget-provider
android:minResizeWidth="180dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="530dp"
android:maxResizeHeight="450dp">
</appwidget-provider>
Как указано в предыдущих атрибутах, ширина виджета может изменяться от 180 до 530 dp, а его высота — от 110 до 450 dp. Размер виджета может изменяться от 3x2 до 5x2 ячеек при соблюдении следующих условий:
- Устройство имеет сетку 5х4.
- Сопоставление количества ячеек и доступного размера в dps приведено в таблице, показывающей оценку минимальных размеров на этой странице.
- Виджет адаптируется к этому диапазону размеров.
Котлин
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))
Ява
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);
Предположим, что виджет использует адаптивные макеты, определённые в предыдущих фрагментах кода. Это означает, что макет, заданный как R.layout.widget_weather_forecast_small
, используется в диапазоне от 180dp ( minResizeWidth
) x 110dp ( minResizeHeight
) до 269x279dp (следующие точки отсечения - 1). Аналогично, R.layout.widget_weather_forecast_medium
используется в диапазоне от 270x110dp до 270x279dp, а R.layout.widget_weather_forecast_large
— в диапазоне от 270x280dp до 530dp ( maxResizeWidth
) x 450dp ( maxResizeHeight
).
При изменении пользователем размера виджета его внешний вид меняется, адаптируясь к каждому размеру ячеек, как показано в следующих примерах.

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
.