Изменение размера виджета в Android 4.1 Jelly Bean

    Как стало известно — в новой версии 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")/80;
             // int appWidgetMaxWidth = (Integer)  b.get("appWidgetMaxWidth");
             // int appWidgetMinHeight = (Integer)  b.get("appWidgetMinHeight");
                int appWidgetMaxHeight = (Integer)  b.get("appWidgetMaxHeight")/100;
    		Log.i("Widget","Width="+appWidgetMinWidth+" Height="+appWidgetMaxHeight);
    

    Отправляются 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 проверить метод, возможно размеры будут изменяться по несколько другой последовательности.
    Поделиться публикацией

    Похожие публикации

    Комментарии 10

      +1
      for (int i=1;i<=10;i++) {
          if  (appWidgetMinWidth==i*80) {w=i; break;}
      }
      


      почему нельзя просто разделить?

        0
        Логично. в принципе можно и разделить сразу при получении, тогда и код будет проще. Просто в процессе появился такой код, но исправлю сейчас.
        0
        Юзаю оболочку GO, она такое научилась делать несколько месяцев назад, очень удобно.
          0
          Специально поставил GO Launcher, но автоматического масштабирования не нашел. в ручную менять размер виджета можно, как и на 90% сторонних лаунчеров, но проблема одна-новые размеры они вряд ли отправяи в отличии от стокового.
            0
            GO очень быстро развивается, я думаю это дело пары недель.
              0
              Вполне возможно, по пока, увы, такой функции нет.
              Да и начиная с Android 4.0 (3.* не пользовался, но там вроде тоже самое) лаунчер стал хорошим, и альтернативный ставить уже смысла нет, на 2.* стоковый лаунчер так себе, поэтому и появилось обилие альтернативных.
                0
                Ну почему же не имеет смысла. Стоковый как был убог так и остался. Андроид 4.0.3.
                1. Нет настроек.
                2. Один тип анимации и тот косой, не в плане плавности, а в плане отзывчивости.
                3. Нет кругового пролистывания.
                4. Нет возможности посмотреть все столы главного экрана.
                5. Нет настроек жестов, стилизации и тп.
                6. Меню приложений грузится полчаса.
                7. Нет возможности задать размер сетки.
                8. Нет возможности задать название папки. (не нашёл).
                9. Нет возможности сразу удалить приложение (не с экрана, а вообще), в го появляется меню, можно удалить приложение, переименовать и тп. Так же само и в меню приложений, он сразу кидает иконку на главный экран, вместо того чтобы спросить действие. В GO, можно просто перетащить иконку вверх, откроется список экранов и поместить куда нужно.
                10. Нет менеджера открытых, недавно посещённых приложений (кнопка home не в счёт).

                В комплекте с GO можно докачать много качественных приложений, виджетов, локскринов, обоев, скинов и тп.
                  0
                  2. Вполне отзывчивый.
                  6. Раз при старте системы загрузилось и все, больше загрузок нет, если конечно не выгружать лаунчер вручную, да и грузится у меня с моими 104 приложениями в списке и кучей виджетов секунд 5 максимум.
                  8. Открываешь папку и снизу её название.
                  9. Заходишь в список приложений и долгий тап и не отпуская перетягиваешь наверх экрана, а там 2 пункта «Удалить приложение» и «Сведения о приложении». Экран при перетягивании можно выбрать, точнее пролестать до необходимого.

                  Да и мне весь этот функционал не нужен, использую всего 2 стола, единственное что было бы хорошо-редактирование размера сетки, но и без него все устраивает.
                  Все по потребностям.
                    0
                    2. Нужно пальцем больше провести чем надо, чтобы сменился экран. На работе имел дело с разработкой сайта под iphone, совсем другие чувства. В го можно подобрать подобное.
                    6. После тяжёлого приложения или игры, лаунчер, как я понял выгружается, и снова приходится ждать чтобы меню приложений заново загрузилось. В го в настройках есть пункт, можно ставить, чтобы лаунчер вовсе не выгружался.
                    9. У меня при долгом тапе сразу кидает на главный экран.
                    8. Да но нет нахвание под иконкой папки. У меня например около 20 игр в папке, в другой браузеры, в третьей муз. проги, в четвёртой всякие приколы. И собственно по значку толком не понять что там внутри, и названия нет.

                    Угу, согласен, что всё по нуждам. У меня просто на главной много столов с виджетами и тп.
                      0
                      6. это из-за малого количества озу. но старом телефоне действительно выгружался любой лаунчер, но Galaxy Nexus максимум раз такое было.
                      9. У меня какой экран был открыт, на тот и предлагает вынести ярлык, а пункты всегда сверху есть
                      8. Ну да, тут названия папок не понятно для чего, вроде они и есть, но тольку от них 0, но я по иконкам все понимаю, да и в 3 папках запутаться сложно.
                      Да и у меня весь главный экран забит виджетами.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое