На этой странице описаны улучшения в настройке размеров виджетов и повышенная гибкость, представленные в 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 adds APIs letting you ensure your widget is sized more reliably across different devices with varying screen sizes.
В дополнение к существующим атрибутам 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) }
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); }
Предположим, что виджет обладает следующими атрибутами:
<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 { }
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) { }
Укажите размер для вашего виджета
Для каждого виджета необходимо задать значения 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 |
| 2х1 | 130x102dp | 269x51dp |
| 3х1 | 203x102dp | 412x51dp |
| 4x1 | 276x102dp | 554x51dp |
| 5x1 | 349x102dp | 697x51dp |
| 5x2 | 349x220dp | 697x117dp |
| 5x3 | 349x337dp | 697x184dp |
| 5x4 | 349x455dp | 697x250dp |
| ... | ... | ... |
| нхм | (73n - 16) x (118m - 16) | (142n - 15) x (66m - 15) |
Используйте размеры ячеек в портретном режиме для определения значений атрибутов minWidth , minResizeWidth и maxResizeWidth . Аналогично, используйте размеры ячеек в альбомном режиме для определения значений атрибутов minHeight , minResizeHeight и maxResizeHeight .
Причина этого в том, что ширина ячейки обычно меньше в портретном режиме, чем в альбомном, и, аналогично, высота ячейки обычно меньше в альбомном режиме, чем в портретном.
Например, если вы хотите, чтобы ширина вашего виджета изменялась до одной ячейки на Google Pixel 4, вам нужно установить значение minResizeWidth не более 56dp, чтобы убедиться, что значение атрибута minResizeWidth меньше 57dp — поскольку в портретном режиме ширина ячейки составляет не менее 57dp. Аналогично, если вы хотите, чтобы высота вашего виджета изменялась до одной ячейки на том же устройстве, вам нужно установить значение minResizeHeight не более 50dp, чтобы убедиться, что значение атрибута minResizeHeight меньше 51dp — поскольку в альбомном режиме высота ячейки составляет не менее 51dp.
Размер каждого виджета можно изменять в пределах диапазонов значений, заданных атрибутами 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>
Как указано в приведенных выше атрибутах, ширина виджета может изменяться от 180dp до 530dp, а его высота — от 110dp до 450dp. Размер виджета также может изменяться от 3x2 до 5x2 ячеек при соблюдении следующих условий:
- Устройство имеет сетку 5x4.
- The mapping between the number of cells and the available size in dps follows the table showing estimation of minimum dimensions in this page.
- Виджет адаптируется к этому диапазону размеров.
Котлин
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);
Предположим, что виджет использует адаптивные макеты, определенные в приведенных выше фрагментах кода. Это означает, что макет, указанный как 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 .
