Как стало известно — в новой версии Android Jelly Bean (API v16) появилась возможность изменения размера виджета, да не просто изменения, а автоматического, который теперь подстраивается под свободное место на экране.
Функция удобная и полезная, но в официальной документации про это почти ничего нету, что довольно странно.
Так как я разрабатываю несколько виджетов, то решил добавить данный функционал.
Первое что я заметил, это то, что виджет вообще не меняет размер, это решилось просто добавлением 3 строк в widget_provider.xml (res/xml):
android:resizeMode="horizontal|vertical"
android:minResizeHeight="72dip"
android:minResizeWidth="72dip"
android:resizeMode отвечает за направление изменения размера виджета и имеет 3 возможных значения:
- horizontal — позволяет растягивать виджет по горизонтали
- vertical — позволяет растягивать виджет по вертикали
- none — запрещает растягивать виджет (по умолчанию)
android:minResizeHeight и android:minResizeWidth отвечают за минимальный размер виджета, который можно выставить.
В коде выше виджет можно растягивать в любом направлении и его минимальный размер 1*1 ячейка.
Вроде все стало отлично, и все работает, однако какого размера стал виджет не ясно.
В документации нашел упоминание метода onAppWidgetExtrasChanged(Context context, AppWidgetManager appWidgetManager,int appWidgetId, Bundle newExtras), который должен вызываться при изменении размера, но у меня он так ни разу и не вызвался.
Далее обнаружилось, что при изменении размера виджету отправляется новый броадкаст "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS". Следуя логике можно было предположить, что с ним должен отправиться и новый размер. Так и оказалось.
Но отправляется он не в очень явном виде. В итоге получился такой код:
final String action = intent.getAction();
if (action.equalsIgnoreCase("android.appwidget.action.APPWIDGET_UPDATE_OPTIONS")) {
Bundle b = intent.getBundleExtra("appWidgetOptions");
int appWidgetMinWidth = (Integer) b.get("appWidgetMinWidth");
// int appWidgetMaxWidth = (Integer) b.get("appWidgetMaxWidth");
// int appWidgetMinHeight = (Integer) b.get("appWidgetMinHeight");
int appWidgetMaxHeight = (Integer) b.get("appWidgetMaxHeight");
int w = 1;
int h = 1;
for (int i=1;i<=10;i++) {
if (appWidgetMinWidth==i*80) {w=i; break;}
}
for (int i=1;i<=10;i++) {
if (appWidgetMaxHeight==(i*100)) {h=i; break;}
}
Log.i("Widget","Width="+w+" Height="+h);
Отправляются 4 размера — минимальная и максимальная ширина и высота. В ходе эксперимента выяснилось, что эти размеры постоянны и удобнее ориентироваться на минимальную ширину и максимальную высоту.
При изменении размера виджета в лог выведется его размер в количестве ячеек. Далее этот размер можно сохранить для данного виджета (его ID: int id = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);) и при обновлении считывать ти данные и подстраивать параметры.
В более ранних версия Android такой функции естественно небыло, и многие разработчики, да и я в том числе, делали несколько размеров виджета, дабы предоставить людям выбор, теперь этот выбор не нужен, поэтому по хорошему, оставить пользователю с Jelly Bean 1 виджет и функцию масштабирования, а пользователям более ранних версий несколько виджетов с разными размерами, но все это что бы было в 1 пакете.
реализовать это оказалось очень просто:
Создаем в папке res/values файл bool.xml с содержимым
<resources>
<bool name="v16">true</bool>
</resources>
И в папке res/values-v16 такой же файл, но нескольки иным содержимым:
<resources>
<bool name="v16">false</bool>
</resources>
После чего в AndroidManifest.xml у ресиверов виджетов, которые необходимо скрыть в новой версии дописываем
android:enabled="@bool/v16"
И все, начиная с API v16 данные виджеты будут отключены, и в списке не отображаться.
P.S. данный метод проверялся на MDPI и HDPI экранах с размером сетки лаунчера 4*4, просьба пользователей планшетов с Android Jelly Bean и размером сетки большим чем 4*4 проверить метод, возможно размеры будут изменяться по несколько другой последовательности.
Автор: BOOMik