Виджеты для android studio

Полный список

— создаем виджет со списком

В третьей версии Андроид у виджетов появилась возможность работать с наборами данных типа списка или грида. Рассмотрим эту технологию на примере списка. В качестве view-компонента используется обычный ListView. Для межпроцессной работы с ним используется, как обычно в виджетах, RemoteViews. Но для заполнения нам придется создать два класса в дополнение к стандартному классу провайдера.

Первый – этот класс будет наполнять наш список значениями. Класс является реализацией интерфейса RemoteViewsService.RemoteViewsFactory, и его методы очень схожи с методами стандартного адаптера. Его обычно везде называют factory. Я же в этом уроке буду называть его просто адаптером.

Второй – класс сервиса, наследующий RemoteViewsService. В нем мы реализуем только один метод, который будет создавать и возвращать экземпляр (первого) класса, который будет заполнять список.

При создании и работе со списком в виджете необходимо понимать, как реализованы два момента: заполнение данными и реакция на нажатия.

Опишу вкратце схему заполнения данными. При подготовке виджета в классе провайдера мы для списка присваиваем Intent, который содержит данные для вызова нашего второго класса-сервиса. Когда система хочет обновить данные в списке (в виджете) она достает этот интент, биндится к указанному сервису и берет у него адаптер. И этот адаптер уже используется для наполнения и формирования пунктов списка.

Теперь о реализации нажатий на пункты списка. В обычном виджете использовались PendingIntent. Здесь чуть по-другому. Для каждого пункта в списке НЕ создается свой отдельный PendingIntent. Вместо этого списку дается общий, шаблонный PendingIntent. А для каждого пункта списка мы указываем отдельный Intent с extra-данными. Далее, при создании, каждому пункту списка система присваивает обработчик нажатия, который при срабатывании берет этот общий PendingIntent, добавляет к нему данные из персонального Intent, и отправляет по назначению сформированный таким образом PendingIntent. Т.е. в итоге по клику все равно срабатывает PendingIntent.

Сделаем пример и рассмотрим на практике все эти теоретические выкладки.

Создадим проект без Activity:

Project name: P1211_ListWidget
Build Target: Android 4.1
Application name: ListWidget
Package name: ru.startandroid.develop.p1211listwidget

Создаем layout-виджета — widget.xml:

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

Теперь layout строки списка – item.xml:

В каждом пункте списка у нас будет только текст.

Создаем класс-адаптер — MyFactory.java:

Методы очень похожи на методы обычного адаптера. Обсудим некоторые.

MyFactory – конструктор. Здесь никаких требований. Я, например, использую конструктор с двумя параметрами – Context и Intent. Этот Intent будет передавать нам сервис при создании адаптера. В нем я передаю адаптеру ID виджета.

getLoadingView – здесь вам предлагается возвращать View, которое система будет показывать вместо пунктов списка, пока они создаются. Если ничего здесь не создавать, то система использует некое дефолтное View.

getViewAt – создание пунктов списка. Здесь идет стандартное использование RemoteViews

onDataSetChanged – вызывается, когда поступил запрос на обновление данных в списке. Т.е. в этом методе мы подготавливаем данные для списка. Метод заточен под выполнение тяжелого долгого кода. В трех первых пунктах списка мы выводим текущее время, хэш-код адаптера и ID-виджета. Позже станет понятно, зачем.

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

Создаем сервис – MyService.java:

В нем мы просто реализуем метод onGetViewFactory, который создает адаптер, передает ему Context и Intent, и возвращает этот созданный адаптер системе.

Класс провайдер – MyProvider.java:

onUpdate вызывается, когда поступает запрос на обновление виджетов. В нем мы перебираем ID, и для каждого вызываем метод updateWidget.

updateWidget – здесь вызываем три метода для формирования виджета и затем метод updateAppWidget, чтобы применить все изменения к виджету.

Читайте также:  Удобный блокнот для андроид

setUpdateTV – в этом методе работаем с TextView (который над списком). Ставим ему время в качестве текста и вешаем обновление виджета по нажатию.

setList – с помощью метода setRemoteAdapter указываем списку, что для получения адаптера ему надо будет обратиться к нашему сервису MyService.

Также обратите внимание, что в Intent мы помещаем ID виджета. Зачем? Этот Intent будет передан в метод сервиса onGetViewFactory. Этот метод мы реализовывали, в нем мы создаем адаптер и передаем ему тот же Intent. А уже в адаптере достаем этот ID и используем (третья строка в списке). Т.е. этот Intent пройдет через сервис и попадет в адаптер, поэтому если хотите что-то передать адаптеру, используйте этот Intent.

Но, повторюсь, это вовсе необязательно. Вы можете создать конструктор адаптера и без Intent-а на вход. Просто мне надо было как-то передать адаптеру ID виджета, поэтому я использую Intent.

setListClick – пока пустой. Чуть позже будем кодить в нем обработку нажатий на пункты списка.

Файл метаданных виджета — res/xml/widget_metadata.xml:

Фрагмент манифеста, описывающий сервис и бродкаст:

Для сервиса, необходимо установить разрешение BIND_REMOTEVIEWS. Это мы не наделяем сервис полномочиями, а наоборот, указываем, что этими полномочиями должен быть наделен тот, кто будет этот сервис вызывать. Система имеет такие полномочия, поэтому сможет использовать сервис для заполнения списка в адаптере.

Непростая это штука – виджеты, правда? Столько телодвижений из-за простого списка 🙂

Все сохраняем, инсталлим виджет. Добавим на экран. В списке он будет называться ListWidget.

Видим время обновления виджета, время формирования данных в списке, хэш-код адаптера, ID виджета.

Жмем зеленую зону для обновления.

Время обновления виджета поменялось, а вот список не обновился, время формирования данных осталось прежним.

Чтобы обновить данные в списке виджета, необходимо явно вызвать метод notifyAppWidgetViewDataChanged и передать ему ID виджета и ID списка.

Давайте сделаем это. Перепишем updateWidget в MyProvider.java:

Добавили вызов обновления данных списка.

Сохраняем, инсталлим. Теперь нажатие на зеленую зону будет обновлять и список.

Теперь давайте добавим второй виджет. У них внезапно совпадают ID виджета и хэш-коды адаптеров.

Вывод: они используют один адаптер. Почему так?

Когда система создает список в виджете, она использует Intent, который мы передавали в метод setRemoteAdapter. В этом Intent мы указали, что надо использовать сервис MyService. Система биндится к MyService и передает ему этот Intent. Сервис проверяет, не был ли уже создан адаптер для такого Intent. Если был – то он и возвращается системе. Если по такому Intent еще не создавался адаптер, то он создается (используется метод onGetViewFactory, который мы реализовали) и возвращается системе. Т.е. некая система кэширования адаптеров по Intent.

Теперь наложим эту логику на нашу ситуацию. Мы создали первый виджет. В метод setRemoteAdapter передавали Intent с указанием класса нашего сервиса и с ID виджета в extra-данных. Сервис создал адаптер, отдал его списку первого виджета и связал эту пару – Intent и адаптер. Далее мы создаем второй виджет. Для его списка, мы использовали такой же Intent. Отличие только в extra-данных – ID виджета. Но сервис сверяет Intent-ы только по основным данным, без extra. Поэтому для него два этих Intent от разных виджетов получились одинаковы. И когда список второго виджета дал Intent и попросил выделить ему адаптер, сервис взял Intent, увидел, что по подобному Intent уже был выдан адаптер и его и использовал вместо того, чтобы новый городить. Т.е. список второго виджета получил тот же адаптер, что и список первого виджета.

Поэтому список второго виджета и показывает те же данные адаптера (ID виджета и хэш-код), что и список первого. Как это пофиксить? Сделать Intent-ы разными. Для этого будем добавлять к ним data, в который поместим все данные Intent. В этом случае у нас в data попадут extra-данные и Intent-ы будут разными.

Читайте также:  Новейшая модель версия андроид

Перепишем метод setList в MyProvider.java:

Теперь все ок. Для разных виджетов получатся разные Intent и списки получат разные адаптеры.

Для чистоты эксперимента удалите пару ранее созданных виджетов с экрана.

Все сохраняем, инсталлим. Размещаем пару виджетов

Все ок, видим, что теперь списки используют разные адаптеры.

Осталось разобраться с реагированием на нажатия пунктов списка.

Добавим пару констант в класс MyProvider.java:

Заполним метод setListClick в MyProvider.java:

Здесь используется обычный алгоритм послания бродкаста. Мы с помощью метода setPendingIntentTemplate устанавливаем шаблонный PendingIntent, который затем будет использоваться всеми пунктами списка. В нем мы указываем, что необходимо будет вызвать наш класс провайдера (он же BroadcastReceiver) с action = ACTION_ON_CLICK.

Теперь нам надо сделать обработку этого action. Добавим метод onReceive в MyProvider.java:

Вызываем метод родителя, чтобы не нарушать работу провайдера. Далее проверяем, что action тот, что нам нужен — ACTION_ON_CLICK, вытаскиваем позицию нажатого пункта в списке и выводим сообщение на экран.

Осталось допилить адаптер. Перепишем getViewAt в MyFactory.java:

Для каждого пункта списка мы создаем Intent, помещаем в него позицию пункта и вызываем setOnClickFillInIntent. Этот метод получает на вход ID View и Intent. Что он с ними делает?

Для View с полученным на вход ID он создает обработчик нажатия, который будет дергать PendingIntent, который получается следующим образом. Берется шаблонный PendingIntent, который был привязан к списку методом setPendingIntentTemplate (в классе провайдера) и к нему добавляются данные полученного на вход Intent-а. Т.е. получится PendingIntent, Intent которого будет содержать action = ACTION_ON_CLICK (это мы сделали еще в провайдере) и данные по позиции пункта списка. При нажатии на пункт списка, этот Intent попадет в onReceive нашего MyProvider и будет обработан, как я уже чуть ранее описывал.

Все сохраняем, инсталлим. Проверяем – нажимаем на какой либо пункт:

Подытожим про LifeCycle-методы. Метод onCreate для адаптера вызывается, когда он создается для первого своего списка. А метод onDestory вызывается, когда удаляется последний список, использующий этот адаптер.

Мы использовали метод setRemoteAdapter. который на вход берет ID View и Intent, этот метод появился только в API 14. А изначально в API 11 была такая реализация — setRemoteAdapter (int appWidgetId, int viewId, Intent intent). Он на вход требовал еще ID виджета. Используйте этот вариант метода, если ваш виджет должен будет работать в Android 3.

У обычного ListView есть возможность установить View, которое будет отображаться если данных в списке нет — метод setEmptyView. RemoteViews также предоставляет вам такую возможность — setEmptyView. На вход передаете ID списка и ID пустого View.

На следующем уроке:

— рассмотрим прочие возможности виджета: превью, изменение размера, экран блокировки, ручное обновление

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Android — Виджеты

Виджет — это небольшой гаджет или элемент управления вашего Android-приложения, размещенный на главном экране. Виджеты могут быть очень удобными, поскольку они позволяют размещать ваши любимые приложения на главном экране для быстрого доступа к ним. Вы, вероятно, видели некоторые распространенные виджеты, такие как виджет музыки, виджет погоды, виджет часов и т. Д.

Виджеты могут быть разных типов, таких как информационные виджеты, виджеты коллекции, виджеты управления и гибридные виджеты. Android предоставляет нам полную основу для разработки наших собственных виджетов.

Читайте также:  Рингтоны для смартфонов андроидов

Виджет — XML-файл

Для создания виджета приложения первым делом вам нужен объект AppWidgetProviderInfo, который вы определите в отдельном XML-файле виджета. Для этого щелкните правой кнопкой мыши свой проект и создайте новую папку с именем xml . Теперь щелкните правой кнопкой мыши по вновь созданной папке и создайте новый файл XML. Тип ресурса файла XML должен быть установлен на AppWidgetProvider . В файле XML определите некоторые свойства, которые следующие:

Виджет — файл макета

Теперь вы должны определить макет вашего виджета в XML-файле по умолчанию. Вы можете перетащить компоненты для генерации автоматического XML.

Виджет — файл Java

После определения макета теперь создайте новый файл JAVA или используйте существующий, расширьте его классом AppWidgetProvider и переопределите его метод обновления следующим образом.

В методе обновления вы должны определить объект двух классов: PendingIntent и RemoteViews. Его синтаксис —

В конце вы должны вызвать метод update updateAppWidget () класса AppWidgetManager. Его синтаксис —

Являясь частью метода updateAppWidget, в этом классе определены другие методы для работы с виджетами. Они заключаются в следующем —

onDeleted (Контекст контекста, int [] appWidgetIds)

Это вызывается, когда экземпляр AppWidgetProvider удаляется.

onDisabled (контекстный контекст)

Это вызывается, когда последний экземпляр AppWidgetProvider удаляется

onEnabled (Контекстный контекст)

Это вызывается, когда создается экземпляр AppWidgetProvider.

onReceive (контекстный контекст, намерение намерения)

Он используется для отправки вызовов различным методам класса

onDeleted (Контекст контекста, int [] appWidgetIds)

Это вызывается, когда экземпляр AppWidgetProvider удаляется.

onDisabled (контекстный контекст)

Это вызывается, когда последний экземпляр AppWidgetProvider удаляется

onEnabled (Контекстный контекст)

Это вызывается, когда создается экземпляр AppWidgetProvider.

onReceive (контекстный контекст, намерение намерения)

Он используется для отправки вызовов различным методам класса

Виджет — файл манифеста

Вы также должны объявить класс AppWidgetProvider в своем файле манифеста следующим образом:

пример

Вот пример, демонстрирующий использование приложения Widget. Он создает базовые приложения-виджеты, которые открывают этот текущий веб-сайт в браузере.

Чтобы поэкспериментировать с этим примером, вам нужно запустить его на реальном устройстве, на котором работает интернет.

Sr.No Метод и описание
1
меры Описание
1 Вы будете использовать Android studio для создания приложения Android в пакете com.example.sairamkrishna.myapplication.
2 Измените файл src / MainActivity.java, чтобы добавить код виджета.
3 Измените res / layout / activity_main, чтобы добавить соответствующие компоненты XML
4 Создайте новую папку и XML-файл в res / xml / mywidget.xml, чтобы добавить соответствующие компоненты XML
5 Измените AndroidManifest.xml, чтобы добавить необходимые разрешения
6 Запустите приложение и выберите работающее устройство Android, установите на него приложение и проверьте результаты.

Ниже приводится содержание измененного MainActivity.java .

Ниже приводится измененное содержимое файла xml res / layout / activity_main.xml .

Ниже приводится содержимое файла res / xml / mywidget.xml .

Ниже приводится содержимое файла res / values ​​/ string.xml .

Ниже приводится содержимое файла AndroidManifest.xml .

Давайте попробуем запустить ваше приложение. Я предполагаю, что вы подключили свое фактическое мобильное устройство Android к компьютеру. Чтобы запустить приложение из студии Android, откройте один из файлов деятельности вашего проекта и нажмите «Выполнить». значок из панели инструментов. Перед запуском приложения Android Studio отобразит следующее окно, чтобы выбрать опцию, в которой вы хотите запустить приложение Android.

Выберите мобильное устройство в качестве опции, а затем проверьте свое мобильное устройство, на котором будет отображаться экран по умолчанию —

Перейдите в раздел виджетов и добавьте созданный виджет на рабочий стол или домашний экран. Это будет выглядеть примерно так —

Теперь просто нажмите на кнопку виджета, которая появляется, чтобы запустить браузер. Но перед этим, пожалуйста, убедитесь, что вы подключены к Интернету. После нажатия кнопки появится следующий экран —

Заметка. Просто изменив URL в файле Java, ваш виджет откроет нужный веб-сайт в браузере.

Источник

Оцените статью