Статьи

Кодирование виджета для Android: ввод и отображение

Начиная с Android 1.5, виджеты приложений позволяют пользователям получать информацию, управлять приложениями и выполнять важные задачи, не выходя из своих домашних экранов.

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

К концу серии вы создадите виджет, который:

  • Отображает несколько наборов данных.
  • Выполняет уникальное действие, когда пользователь взаимодействует с определенным View в макете этого виджета.
  • Обновляется автоматически по истечении заданного периода времени.
  • Обновления с новыми данными в ответ на взаимодействие с пользователем.

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

Виджет приложения — это легкое миниатюрное приложение, которое обычно относится к одной из следующих категорий:

  • Информационный виджет. Не прокручиваемый виджет, который отображает важную информацию, такую ​​как виджет погоды или часов.
  • Коллекция виджетов. Прокручиваемый виджет, который отображает ряд связанных элементов, таких как галерея фотографий или статей из той же публикации. Коллекционные виджеты обычно поддерживаются источником данных, таким как Array или база данных. Виджет коллекции должен включать в себя ListView , GridView , StackView или AdapterViewFlipper .
  • Управляйте виджетами. Виджет, который выступает в качестве пульта дистанционного управления для вашего приложения, позволяя пользователю запускать часто используемые функции без необходимости запуска вашего приложения. Приложения, которые воспроизводят музыку, часто предоставляют виджет, который позволяет пользователю воспроизводить, приостанавливать и пропускать дорожки прямо со своего домашнего экрана.
  • Гибридные виджеты. Зачем ограничивать себя одной категорией, если вы можете выбирать элементы из нескольких категорий? Просто имейте в виду, что смешивание и сопоставление могут привести к путанице в работе пользователя, поэтому для достижения наилучших результатов вы должны разработать свой виджет с учетом одной категории, а затем добавлять элементы из других категорий по мере необходимости. Например, если вы хотите создать виджет, который отображает прогноз погоды на сегодня, но также позволяет пользователям просматривать прогноз для разных дней и местоположений, вам следует создать информационный виджет, а затем добавить необходимые элементы управления.

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

Виджеты приложений должны быть размещены внутри хоста виджетов приложений , чаще всего на стандартном домашнем экране Android, хотя есть некоторые сторонние хосты виджетов приложений, такие как популярные Nova Launcher и Apex Launcher .

На протяжении всей этой серии я буду говорить о виджетах как о чем-то, что вы помещаете на домашний экран, но если у вас есть смутные воспоминания о возможности разместить виджеты на экране блокировки, то это был не просто какой-то чудесный сон! Между уровнями API 17 и 20 можно было размещать виджеты на домашнем экране или на экране блокировки.

Так как виджеты блокировки экрана устарели на уровне API 21, в этой серии мы создадим виджет только для домашнего экрана.

Есть несколько причин, почему вы должны рассмотреть возможность добавления виджета приложения в ваш последний проект Android.

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

Если вы разрабатываете виджет управления (или гибридный виджет с элементами управления), пользователь также может выполнять задачи прямо со своего домашнего экрана. Продолжая наш пример с календарем, ваш виджет может позволить пользователю создавать, редактировать и отменять встречи, даже не запуская ваше приложение. Это может удалить несколько шагов навигации из некоторых наиболее важных задач вашего приложения, что может оказать только положительное влияние на взаимодействие с пользователем!

При нажатии на виджет пользователь обычно переходит на верхний уровень связанного приложения, аналогично ярлыку приложения. Однако, в отличие от ярлыков приложений, виджеты могут ссылаться на определенные области в связанном приложении. Например, если нажать на уведомление о получении нового электронного сообщения от виджета, можно запустить приложение с уже выбранным новым сообщением, а при нажатии « Создать новое электронное письмо» они могут быть ComposeEmail непосредственно в активность приложения ComposeEmail .

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

Как доказал весь взрыв Pokemon Go и последующее прекращение его работы, получение тонны людей для загрузки вашего приложения не гарантирует автоматически базу лояльных пользователей, которые все еще будут использовать ваше приложение дни, недели или даже месяцы .

Мобильные пользователи — довольно изменчивая группа, и с ростом памяти, доступной на вашем обычном Android-смартфоне или планшете, легко потерять отслеживание приложений, установленных на вашем устройстве. Скорее всего, если вы возьмете свой Android-смартфон или планшет прямо сейчас и проведете через панель приложений, то вы обнаружите хотя бы одно приложение, о котором вы полностью забыли.

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

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

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

Как только Android Studio создаст ваш проект, выберите « Файл»> «Создать»> «Виджет»> «AppWidget» на панели инструментов «Android Studio». Это запускает меню Configure Component, где вы можете определить некоторые из начальных настроек вашего виджета.

Настройте параметры виджетов в Android Studio

Большинство из этих вариантов довольно очевидны, но есть некоторые, которые стоит изучить более подробно.

Если размер виджета можно изменить, пользователь может увеличивать или уменьшать количество «ячеек», которые он занимает на рабочем столе, долгим нажатием на виджет и затем перетаскивая синие маркеры, которые появляются вокруг его контура.

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

Если вы хотите создать виджет без изменения размера, откройте раскрывающееся меню «Изменить размер» и выберите « Только по горизонтали» , « Только по вертикали» или « Не изменять размер» .

Минимальная ширина и высота определяет количество ячеек, которые ваш виджет будет первоначально занимать при размещении на рабочем столе.

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

Если размер вашего виджета не изменяется, то минимальные значения ширины и высоты — это постоянные ширина и высота вашего виджета.

Чтобы увеличить шансы удобного размещения виджета на ряде домашних экранов, никогда не рекомендуется использовать что-либо большее, чем 4 на 4, для минимальных значений ширины и высоты.

Хотя точная ширина и высота «ячейки» домашнего экрана варьируются в зависимости от устройства, вы можете получить приблизительную оценку того, сколько точек на дюйм (точек на дюйм) будет занимать ваш виджет, используя следующую формулу:

1
70 × number of cells -30

Например, если ваш виджет имеет 2 х 3 ячейки:

1
2
70 x 2 — 30 = 110
70 x 3 — 30 = 180

Этот виджет будет занимать около 110 x 180 точек на дюйм на домашнем экране пользователя. Если эти значения не совпадают с размерами ячеек определенного устройства, Android автоматически округлит ваш виджет до ближайшего размера ячейки.

Просмотрите все параметры в этом меню и внесите необходимые изменения (я придерживаюсь настроек по умолчанию), а затем нажмите « Готово» .

Android Studio теперь сгенерирует все файлы и ресурсы, необходимые для доставки основного виджета приложения. Этот виджет не совсем интересен (в основном это синий блок с надписью « Пример» ), но это функциональный виджет, который вы можете протестировать на своем устройстве.

Чтобы проверить виджет:

  • Установите свой проект на физическое устройство Android или AVD (Android Virtual Device).
  • Запустите средство выбора виджетов для Android нажав любое пустое место на рабочем столе, а затем коснувшись виджета со словом, который появляется в нижней части экрана.
  • Проведите пальцем по палитре виджетов, пока не увидите синий виджет « Пример» .
  • Нажмите на этот виджет, чтобы разместить его на рабочем столе.
  • Войдите в режим изменения размера , нажимая на виджет до тех пор, пока не появится набор синих маркеров, а затем перетащите эти маркеры, чтобы увеличить или уменьшить количество ячеек, занимаемых этим виджетом.
Проверьте свой виджет на виртуальном Android

Этот виджет может делать не так много, но он включает в себя все классы и ресурсы, над которыми мы будем работать в оставшейся части этой серии, поэтому давайте посмотрим на эти файлы и их роль в доставке виджета приложения.

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

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

Хотя мы склонны думать о виджете как об едином объекте, который пользователь размещает на своем домашнем экране один раз, ничто не мешает ему создавать несколько экземпляров одного и того же виджета. Возможно, ваш виджет настраивается до такой степени, что разные экземпляры могут иметь существенно различную функциональность, или, может быть, пользователь просто настолько любит ваш виджет, что ему хочется намазать его на весь рабочий стол!

Давайте посмотрим на различные методы жизненного цикла, которые вы можете реализовать в классе провайдера виджетов:

Android вызывает метод onReceive() зарегистрированного BroadcastReceiver всякий раз, когда происходит указанное событие.

Обычно вам не нужно реализовывать этот метод вручную, поскольку класс AppWidgetProvider автоматически фильтрует все широковещательные рассылки виджетов и делегирует операции соответствующим методам.

onEnabled() жизненного цикла onEnabled() вызывается в ответ на ACTION_APPWIDGET_ENABLED , который транслируется, когда пользователь добавляет первый экземпляр вашего виджета на свой ACTION_APPWIDGET_ENABLED . Если пользователь создает два экземпляра вашего виджета, то onEnabled() вызывается для первого экземпляра, но не для второго.

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

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

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

onUpdate() жизненного цикла onUpdate() вызывается каждый раз:

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

onUpdate() жизненного цикла onUpdate() также вызывается в ответ на ACTION_APPWIDGET_RESTORED , который транслируется всякий раз, когда виджет восстанавливается из резервной копии.

Для большинства проектов метод onUpdate() будет содержать основную часть кода провайдера виджета, тем более что здесь также регистрируются обработчики событий вашего виджета.

Метод onDeleted() вызывается каждый раз, когда экземпляр вашего виджета удаляется с хоста виджета приложения, который запускает трансляцию ACTION_APPWIDGET_DELETED системы.

Этот метод вызывается в ответ на трансляцию ACTION_APPWIDGET_DISABLED , которая отправляется, когда последний экземпляр вашего виджета удаляется с хоста виджета приложения. Например, если пользователь создал три экземпляра вашего виджета, метод onDisabled() будет вызываться только тогда, когда пользователь удаляет третий и последний экземпляр со своего onDisabled() .

В onDisabled() жизненного цикла onDisabled() вы должны очистить все ресурсы, созданные в onEnabled() , поэтому, если вы настроите базу данных в onEnabled() вы удалите ее в onDisabled() .

Метод onRestored() вызывается в ответ на ACTION_APPWIDGET_RESTORED , который транслируется всякий раз, когда экземпляр виджета приложения восстанавливается из резервной копии. Если вы хотите сохранить какие-либо постоянные данные, то вам нужно переопределить этот метод и переназначить предыдущие AppWidgetIds на новые значения, например:

1
2
3
4
public void onRestored(Context context, int[] oldWidgetIds,
           int[] newWidgetIds) {
   }
}

Если вы откроете файл NewAppWidget.java, который автоматически сгенерировал Android Studio, вы увидите, что он уже содержит реализации некоторых из этих методов жизненного цикла виджета:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;
 
//All widgets extend the AppWidgetProvider class//
 
public class NewAppWidget extends AppWidgetProvider {
 
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                              int appWidgetId) {
 
      CharSequence widgetText = context.getString(R.string.appwidget_text);
 
    //Load the layout resource file into a RemoteViews object//
 
      RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
      views.setTextViewText(R.id.appwidget_text, widgetText);
 
 //Tell the AppWidgetManager about the updated RemoteViews object//
 
      appWidgetManager.updateAppWidget(appWidgetId, views);
  }
 
//Define the onUpdate lifecycle method//
 
  @Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
 
//appWidgetIds is an array of IDs that identifies every instance of your widget, so this
//particular onUpdate() method will update all instances of our application widget//
 
      for (int appWidgetId : appWidgetIds) {
          updateAppWidget(context, appWidgetManager, appWidgetId);
      }
  }
 
  @Override
 
//Define the onEnabled lifecycle method//
 
  public void onEnabled(Context context) {
       
      //To do//
  }
 
  @Override
 
//Define the onDisabled method//
 
  public void onDisabled(Context context) {
       
//To do//
 
  }
}

Файл res / layout / new_app_widget.xml определяет макет нашего виджета, который в настоящее время представляет собой просто синий фон с надписью « Пример» .

Основное различие между созданием макета для Activity и созданием макета для виджета заключается в том, что макеты виджетов должны основываться на RemoteViews , поскольку это позволяет Android отображать макет в процессе вне вашего приложения (то есть на домашнем экране пользователя).

RemoteViews не поддерживают все виды макетов или View , поэтому при создании макета виджета вы ограничены следующими типами:

  • AnalogClock
  • Button
  • Chromometer
  • FrameLayout
  • GridLayout
  • ImageButton
  • ImageView
  • LinearLayout
  • ProgressBar
  • RelativeLayout
  • TextView
  • ViewStub

Если вы создаете виджет коллекции, вы также можете использовать следующие типы, когда ваше приложение установлено на Android 3.0 и выше:

  • AdapterViewFlipper
  • GridView
  • ListView
  • StackView
  • ViewFlipper

Подклассы и потомки вышеупомянутых Views и классов не поддерживаются.

Щелчки и Размах

Чтобы пользователи случайно не взаимодействовали с виджетом во время навигации по своему домашнему экрану, виджеты реагируют только на события onClick .

Исключение составляют случаи, когда пользователь удаляет виджет, перетаскивая его к действию « Удалить» на домашнем экране, так как в этом случае ваш виджет будет реагировать на жест вертикальной прокрутки. Тем не менее, поскольку этим взаимодействием управляет система Android, вам не нужно беспокоиться о реализации поддержки вертикальной прокрутки в вашем приложении.

Файл res / xml / new_app_widget_info.xml (также известный как файл AppWidgetProviderInfo) определяет ряд свойств виджета, включая многие параметры, выбранные в меню « Конфигурировать компонент» в Android Studio, например минимальные размеры вашего виджета и возможность их размещения. на экране блокировки.

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

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

Если вы откроете файл своего проекта new_app_widget_info.xml , то увидите, что он уже определяет ряд свойств виджета, включая интервал обновления.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version=»1.0″ encoding=»utf-8″?>
<appwidget-provider xmlns:android=»http://schemas.android.com/apk/res/android»
 
//The layout your widget should use when it’s placed on the lockscreen on supported devices//
 
  android:initialKeyguardLayout=»@layout/new_app_widget»
 
//The layout your widget should use when it’s placed on the homescreen//
 
  android:initialLayout=»@layout/new_app_widget»
 
//The minimum space your widget consumes, which is also its initial size//
 
  android:minHeight=»40dp»
  android:minWidth=»40dp»
 
//The drawable that represents your widget in the Widget Picker//
 
  android:previewImage=»@drawable/example_appwidget_preview»
 
//Whether the widget can be resized horizontally, vertically, or along both axes, on Android 3.1 and higher//
 
  android:resizeMode=»horizontal|vertical»
 
//How frequently your widget should request new information from the app widget provider//
 
  android:updatePeriodMillis=»86400000″
 
//Whether the widget can be placed on the homescreen, lockscreen (“keyguard”) or both.//
//On Android 5.0 and higher, home_screen is the only valid option//
 
  android:widgetCategory=»home_screen»></appwidget-provider>

Если вы дадите своим пользователям возможность разместить свой виджет на экране блокировки, имейте в виду, что содержимое виджета будет видно любому, кто даже взглянет на экран блокировки. Если ваш макет «по умолчанию» содержит какую-либо личную или потенциально конфиденциальную информацию, вы должны предоставить альтернативный макет для вашего виджета, который будет использоваться, когда он размещен на экране блокировки.

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

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

Виджет состоит из ограничивающих рамок, поля виджета, полей виджета и элементов управления виджета.

Если ваше приложение запускается на устройстве, которое работает на более ранних версиях, чем Android 4.0, тогда ваш виджет должен сам предоставить этот отступ.

Когда вы создаете виджет с помощью меню «Файл»> «Создать»> «Виджет»> «AppWidget» , Android Studio создает два файла измерения. Xml, которые гарантируют, что ваш виджет всегда будет иметь правильные отступы, независимо от версии Android, на которой он установлен.

Вы найдете оба этих файла в папке res вашего проекта:

res / values ​​/ d imens.xml

Этот файл определяет 8 dpi отступа, который должен предоставлять ваш виджет при установке на уровне API 13 или более ранней версии.

1
<dimen name=»widget_margin»>8dp</dimen>

RES / значения-V14 / dimens.xml

Поскольку Android 4.0 и выше автоматически применяет заполнение к каждому виджету, любые дополнения, которые предоставляет ваш виджет, будут в дополнение к этому заполнению по умолчанию.

Чтобы обеспечить соответствие вашего виджета любым значкам приложений или другим виджетам, которые пользователь разместил на своем домашнем экране, этот файл измерения. Xml указывает, что ваш виджет не должен содержать дополнительных полей для Android 4.0 и выше:

1
<dimen name=»widget_margin»>0dp</dimen>

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

Макет вашего виджета уже ссылается на это значение измерения (android:padding="@dimen/widget_margin") поэтому будьте осторожны, чтобы не изменять эту строку при работе над макетом вашего виджета.

Несмотря на то, что эти размеры. XML- файлы — это самый простой способ убедиться , что ваш виджет всегда имеет правильное заполнение, если этот метод не подходит для вашего конкретного проекта, то одна из альтернатив — создать несколько фонов из девяти патчей с разными полями для уровня API 14. и выше, и уровень API 13 и ниже. Вы можете создавать девять патчей с помощью инструмента Draw 9-patch в Android Studio или с помощью специальной программы для редактирования графики, такой как Adobe Photoshop.

В файле AndroidManifest.xml вашего проекта необходимо зарегистрировать свой виджет в качестве BroadcastReceiver и указать поставщика виджетов и файл AppWidgetProviderInfo, который этот виджет должен использовать.

Если вы откроете манифест, вы увидите, что Android Studio уже добавила всю эту информацию для вас.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//The widget’s AppWidgetProvider;
 
<receiver android:name=».NewAppWidget»>
      <intent-filter>
 
//An intent filter for the android.appwidget.action.APPWIDGET_UPDATE action//
 
          <action android:name=»android.appwidget.action.APPWIDGET_UPDATE» />
      </intent-filter>
 
      <meta-data
          android:name=»android.appwidget.provider»
 
//The widget’s AppWidgetProviderInfo object//
 
          android:resource=»@xml/new_app_widget_info» />
 
  </receiver>
</application>

Файл res / drawable / example_appwidget_preview.png является ресурсом для рисования, который представляет ваш виджет в средстве выбора виджетов.

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

Когда вы создаете виджет с помощью меню «Файл»> «Создать»> «Виджет»> «AppWidget» , Android Studio автоматически создает предварительный просмотр ( example_appwidget_preview.png ).

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

Теперь у нас есть обзор того, как эти файлы собираются вместе, чтобы создать виджет приложения, давайте расширим этот фундамент и создадим виджет, который будет больше, чем просто отображать слово « Пример» на синем фоне!

Мы добавим следующую функциональность в наш виджет:

  • TextView , отображающий метку идентификатора виджета приложения .
  • TextView который получает и отображает идентификатор для этого конкретного экземпляра виджета.
  • TextView который реагирует на события onClick , запуская браузер пользователя по умолчанию и загружая URL.

Хотя мы могли бы просто перетащить три TextViews из палитры Android Studio и поместить их на холст, если ваш виджет выглядит хорошо, пользователи с большей вероятностью разместят его на своем домашнем экране, поэтому давайте создадим некоторые ресурсы, которые придадут нашему виджету дополнительную визуальность. обжалованию.

Я собираюсь создать прямоугольник с закругленными углами, градиентным фоном и рамкой, который я буду использовать в качестве фона для своего виджета:

  • Удерживая клавишу Control, щелкните на папке для рисования вашего проекта и выберите « Создать»> «Файл доступных для рисования ресурсов» .
  • Назовите этот файл widget_background и нажмите OK .
  • Введите следующий код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<?xml version=»1.0″ encoding=»UTF-8″?>
http://schemas.android.com/apk/res/android»
  android:shape=»rectangle»>
 
  <stroke
      android:width=»1dp»
      android:color=»#ffffff» />
 
  <gradient
      android:angle=»225″
      android:endColor=»#00FFFFFF»
      android:startColor=»#DD000000″ />
 
  <corners
      android:topRightRadius=»10dp»
      android:topLeftRadius=»10dp»
      android:bottomRightRadius=»10dp»
      android:bottomLeftRadius=»10dp» />
</shape>

Затем создайте фигуру для использования в качестве фона для наших TextViews :

  • Удерживая клавишу Control, щелкните на папке для рисования вашего проекта и выберите « Создать»> «Файл доступных для рисования ресурсов» .
  • Назовите этот файл tvbackground и затем нажмите OK .
  • Введите следующий код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<?xml version=»1.0″ encoding=»utf-8″?>
http://schemas.android.com/apk/res/android»
  android:shape=»rectangle» >
 
  <stroke
      android:width=»1dp»
      android:color=»#000000″ />
 
  <solid android:color=»#FFFFFFFF» />
 
  <corners
      android:topRightRadius=»15dp»
      android:topLeftRadius=»15dp»
      android:bottomRightRadius=»15dp»
      android:bottomLeftRadius=»15dp» />
</shape>

Я также собираюсь использовать следующие стили:

  • widget_text . Смелый эффект, который я буду применять к тексту виджета.
  • widget_views . Различные поля и отступы, которые я буду применять к моим TextViews .

Откройте файл styles.xml вашего проекта и добавьте следующее:

01
02
03
04
05
06
07
08
09
10
11
<style name=»widget_views» parent=»@android:style/Widget»>
      <item name=»android:padding»>8dp</item>
      <item name=»android:layout_marginTop»>12dp</item>
      <item name=»android:layout_marginLeft»>12dp</item>
      <item name=»android:layout_marginRight»>12dp</item>
      <item name=»android:textStyle»>bold</item>
  </style>
 
<style name=»widget_text» parent=»@android:style/Widget»>
  <item name=»android:textStyle»>bold</item>
</style>

Теперь, когда все наши ресурсы готовы, мы можем создать макет нашего виджета. Откройте файл new_app_widget.xml и добавьте следующее:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»
  android:layout_width=»match_parent»
  android:layout_height=»match_parent»
  android:padding=»@dimen/widget_margin»
  android:background=»@drawable/widget_background»
  android:orientation=»vertical» >
 
  <LinearLayout
      android:background=»@drawable/tvbackground»
      style=»@style/widget_views»
      android:layout_width=»match_parent»
      android:layout_height=»wrap_content»
      android:orientation=»horizontal»>
 
      <TextView
          android:id=»@+id/id_label»
          android:layout_width=»wrap_content»
          android:layout_height=»wrap_content»
          android:text=»@string/widget_id»
          style=»@style/widget_text» />
 
      <TextView
          android:id=»@+id/id_value»
          android:layout_width=»wrap_content»
          android:layout_height=»wrap_content»
          android:text=».»
          style=»@style/widget_text» />
  </LinearLayout>
 
  <TextView
      android:id=»@+id/launch_url»
      style=»@style/widget_views»
      android:layout_width=»wrap_content»
      android:layout_height=»wrap_content»
      android:text=»@string/URL»
      android:background=»@drawable/tvbackground»/>
</LinearLayout>

Наконец, откройте файл strings.xml и определите строковые ресурсы, на которые мы ссылались в нашем макете:

1
2
3
4
5
<resources>
  <string name=»app_name»>Widget</string>
  <string name=»widget_id»>App Widget ID\u0020</string>
  <string name=»URL»>Tap to launch URL</string>
</resources>

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

К сожалению, Android Studio не предоставляет выделенную обложку виджета, поэтому по умолчанию макет вашего виджета отображается так же, как обычная активность, которая не дает лучшего представления о том, как ваш виджет будет выглядеть на домашнем экране пользователя.

Одним из возможных путей решения этой проблемы является визуализация макета с использованием оболочки Android Wear (Square) , которая сопоставима с размером и формой виджета приложения Android:

  • Убедитесь, что выбрана вкладка « Устройство » в Android Studio.
  • Откройте раскрывающийся список устройств .
  • Выберите 280 x 280, hdpi (квадрат) в раскрывающемся меню.
Попробуйте отрисовать макет виджета, используя скин Android Wear Square

Теперь, когда наш виджет выглядит, пришло время дать ему некоторую функциональность:

  • Получить и отобразить данные. Каждому экземпляру виджета присваивается идентификатор при добавлении на хост виджетов приложений. Этот идентификатор сохраняется в течение всего жизненного цикла виджета и будет полностью уникальным для этого экземпляра виджета, даже если пользователь добавляет несколько экземпляров одного и того же виджета на свой домашний экран.
  • Добавить действие. Мы создадим OnClickListener который запускает браузер пользователя по умолчанию и загружает URL.

Откройте файл поставщика виджетов ( NewAppWidget.java ) и удалите строку, которая извлекает строковый ресурс appwidget_text :

01
02
03
04
05
06
07
08
09
10
11
12
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                          int appWidgetId) {
 
//Delete the following line//
 
  CharSequence widgetText = context.getString(R.string.appwidget_text);
  RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
  views.setTextViewText(R.id.appwidget_text, widgetText);
 
  appWidgetManager.updateAppWidget(appWidgetId, views);
 
}

В блоке updateAppWidget нам теперь нужно обновить местозаполнитель R.id.id_value уникальный идентификатор виджета:

1
2
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
     views.setTextViewText(R.id.id_value, String.valueOf(appWidgetId));

Нам также необходимо создать объект Intent, содержащий URL-адрес, который должен загружаться всякий раз, когда пользователь взаимодействует с этим TextView .

1
2
3
4
5
6
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(«https://code.tutsplus.com/»));
      PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
 
//Attach an OnClickListener to our “launch_url” button, using setOnClickPendingIntent//
 
      views.setOnClickPendingIntent(R.id.launch_url, pendingIntent);

Вот полный файл поставщика виджетов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
 
public class NewAppWidget extends AppWidgetProvider {
 
  static void updateAppWidget(Context context,
 
                              AppWidgetManager appWidgetManager,
 
                              int appWidgetId) {
 
//Instantiate the RemoteViews object//
 
      RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
 
//Update your app’s text, using the setTextViewText method of the RemoteViews class//
 
      views.setTextViewText(R.id.id_value, String.valueOf(appWidgetId));
 
//Register the OnClickListener//
 
      Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(«https://code.tutsplus.com/»));
      PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
      views.setOnClickPendingIntent(R.id.launch_url, pendingIntent);
      appWidgetManager.updateAppWidget(appWidgetId, views);
 
  }
 
  @Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
 
      //Update all instances of this widget//
 
      for (int appWidgetId : appWidgetIds) {
          updateAppWidget(context, appWidgetManager, appWidgetId);
      }
  }
}

Пришло время проверить этот виджет!

  • Установите обновленный проект на ваше устройство Android.
  • Чтобы убедиться, что вы видите последнюю версию этого виджета, удалите все существующие экземпляры виджета с рабочего стола.
  • Нажмите любой пустой раздел на главном экране, а затем выберите свой виджет из средства выбора виджетов.
  • Переместите и измените размер виджета по желанию.
Поместите свой виджет приложения Android в тесте
  • Убедитесь, что виджет реагирует на события пользовательского ввода, выбрав Коснитесь, чтобы запустить URL TextView . Виджет приложения должен ответить, запустив браузер по умолчанию и загрузив URL.

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

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

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

А пока посмотрите другие наши замечательные посты о разработке приложений для Android здесь, на Envato Tuts +!

  • Android SDK
    Что такое мгновенные приложения для Android?
  • Android SDK
    Создание доступных приложений для Android
  • Android SDK
    Создание интерфейса с вкладками «Дизайн материала» в приложении для Android
    Чике Мгбемена
  • Android SDK
    Совет: создайте пользовательскую плитку быстрых настроек для Android
    Ашраф Хатхибелагал