На этой странице описаны усовершенствования размера виджетов и большая гибкость, представленная в 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, учитывая желаемое количество занятых ячеек сетки:
Количество ячеек (ширина х высота) | Доступный размер в портретном режиме (dp) | Доступный размер в ландшафтном режиме (dp) |
---|---|---|
1х1 | 57x102dp | 127 x 51 дп |
2х1 | 130 x 102 дп | 269 x 51 дп |
3х1 | 203 x 102 дп | 412 x 51 дп |
4x1 | 276 x 102 дп | 554 x 51 дп |
5x1 | 349 x 102 дп | 697 x 51 дп |
5x2 | 349 x 220 пикселей | 697x117dp |
5х3 | 349 x 337 дп | 697x184dp |
5х4 | 349 x 455 дп | 697x250 пикселей |
... | ... | ... |
нхм | (73н – 16) х (118м – 16) | (142н – 15) х (66м – 15) |
Используйте размеры ячеек портретного режима, чтобы указать значения, которые вы предоставляете для атрибутов minWidth
, minResizeWidth
и maxResizeWidth
. Аналогичным образом используйте размеры ячеек ландшафтного режима, чтобы указать значения, которые вы предоставляете для атрибутов minHeight
, minResizeHeight
и maxResizeHeight
.
Причина этого в том, что ширина ячейки в портретном режиме обычно меньше, чем в альбомном, и, аналогично, высота ячейки в альбомном режиме обычно меньше, чем в портретном.
Например, если вы хотите, чтобы ширина вашего виджета изменялась до одной ячейки на Google Pixel 4, вам необходимо установить для minResizeWidth
не более 56dp, чтобы убедиться, что значение атрибута minResizeWidth
меньше 57dp, поскольку ячейка ширина не менее 57 dp в портретной ориентации. Аналогично, если вы хотите, чтобы высота вашего виджета изменялась в одной ячейке на одном и том же устройстве, вам необходимо установить для 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 ячеек при соблюдении следующих условий:
- Устройство имеет сетку 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
).
Когда пользователь изменяет размер виджета, его внешний вид меняется, адаптируясь к каждому размеру ячеек, как показано в следующих примерах.