Статьи

Используйте jQuery Mobile для создания собственного приложения для чтения новостей Android

В этой серии из трех частей наша главная цель — описать, как jQuery Mobile можно использовать для разработки нативного приложения для Android. Сначала мы разработаем отдельное примерное веб-приложение, которое будет просматривать статьи из Yahoo! Новости с помощью jQuery Mobile. Затем мы с минимальными усилиями преобразуем это веб-приложение в нативное Android-приложение.

Проект jQuery Mobile представляет собой мобильный веб-фреймворк. Альфа-версия выпущена в ноябре 2010 года. Фреймворк можно использовать для разработки кроссплатформенных мобильных веб-приложений для ОС Android, iOS, Blackberry OS и аналогичных платформ (для полной совместимости). Таблица совместимости, см. http://jquerymobile.com/gbs/ ). Хотя платформа была разработана для создания кросс-мобильных веб-приложений, можно также использовать jQuery Mobile для разработки нативных приложений для Android. Следовательно, цель этого урока состоит из двух частей:

Сначала мы проиллюстрируем динамическое построение основных элементов пользовательского интерфейса в jQuery Mobile . Для этого мы будем реализовывать пример веб-приложения под названием «Новости» для просмотра новостных статей из Yahoo! Новости. Приложение отправит HTTP-запросы на основе AJAX на сервер и проанализирует XML-ответ для создания пользовательского интерфейса. Мы будем использовать плагин jquery-dotimeout-plugin, чтобы проиллюстрировать технику анимации, где заголовки новостей отображаются один за другим с периодическими интервалами с эффектом постепенного появления / исчезновения. Это даст читателю представление о форматировании контента для списков jQuery Mobile, в частности, «разделенного списка». Мы также будем использовать плагин DST.js для хранения текущих категорий новостей пользователя в локальном хранилище HTML5. Веб-приложение состоит из файла HTML, содержащего код пользовательского интерфейса, библиотеки jQuery Mobile и плагины jQuery. HTML-файл также использует простой PHP-файл, который перенаправляет HTTP-запросы в Yahoo! Новости URL и отправляет ответ обратно в файл HTML. Это метод, позволяющий обойти ограничение AJAX-запросов в том же источнике в веб-браузерах. Файл PHP не выполняет каких-либо манипуляций с запросом или ответом, так как основная цель состоит в том, чтобы использовать API-интерфейсы jQuery / jQuery Mobile для создания запроса, анализа ответа и создания пользовательского интерфейса. Мы предоставим изображения экрана веб-приложения на устройствах с ОС Android и iOS, чтобы проиллюстрировать тот факт, что пользовательский интерфейс имеет согласованный внешний вид на разных платформах.

Во-вторых, мы продемонстрируем, как разработать нативное приложение для Android, в котором пользовательский интерфейс кодируется с помощью платформы jQuery Mobile . Для этой цели мы будем использовать ранее разработанное веб-приложение. Основная идея заключается в использовании объекта android.webkit.WebView в качестве контейнера для запуска файла HTML в веб-приложении. Единственное необходимое изменение в файле HTML — это направление запросов AJAX в Yahoo! URL-адрес новостей вместо файла PHP. Мы покажем, как интегрировать HTML-файл, содержащий код пользовательского интерфейса, с android.app.Activity и android.webkit.WebViewClient . Мы также покажем, как создавать значки запуска для нашего Android-приложения на основе Android Icon Guidelines .

Файлы, необходимые для работы в Интернете и нативных приложений Android, доступны для загрузки в рамках этой серии руководств. Для приложения Android мы опишем, как импортировать файлы проекта в Eclipse IDE.

Это руководство, первое в нашей серии, организовано следующим образом: в разделе «Поток страниц» мы начинаем знакомить с приложением, предоставляя изображения на экране и описывая поток страниц. Затем мы обсудим некоторые технические детали веб-приложения в разделе «Модель запроса / ответа». В разделе «Структура страницы» мы представляем элементы jQuery Mobile для создания наших страниц.

Во втором уроке из этой серии мы завершаем разработку веб-приложения. Мы продолжаем представлять код jQuery Mobile, динамически создавать разделенный список, обсуждаем технику анимации текста в элементе разделенного списка и предоставляем переходы между страницами в нашем приложении. Специальный раздел второго учебного пособия посвящен объяснению того, как мы работаем вокруг ограничения AJAX-запросов в том же источнике в веб-приложении. Снимки экрана конечного веб-приложения на устройствах iOS и Android представлены для сравнения друг с другом.

Третий и последний учебник из этой серии посвящен переносу веб-приложения в собственное приложение Android. Этот учебник будет включать в себя высокоуровневое описание изменений, необходимых для преобразования нашего веб-приложения в приложение Android, с особым вниманием, android.webkit.WebViewClient классам android.app.Activity и android.webkit.WebViewClient и проверке файлов конфигурации. AndroidManifest.xml и strings.xml . Также будет обсуждаться процесс установки значка запуска приложения и общая файловая структура нашего проекта Android.


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

Первая страница — это страница Категории, на которой пользователь может быстро просмотреть заголовки всех новостей в различных категориях:

категории

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

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

На странице категорий, если пользователь нажимает кнопку добавления, отображается страница выбора категории (рисунок 2):

Выбор категории

На этой странице пользователь выбирает категорию новостей из списка и нажимает кнопку «Получить категорию», чтобы добавить категорию на страницу «Категории».

На странице категорий нажатие на текстовый раздел элемента списка для категории переводит пользователя на страницу новостей, где отображаются все элементы новостей в этой категории (рисунок 3):

Новости

На странице новостей с новостной статьей может быть связано изображение, которое служит ссылкой для получения дополнительной информации о конкретной новости. Нажатие на картинку переводит пользователя на страницу новостей (рисунок 4):

Новости подробно

Обратите внимание, что в веб-приложении страница сведений о новостях отображается в браузере вне HTML-страницы, на которой выполняется код приложения. Чтобы вернуться назад, пользователь должен нажать кнопку «Назад» в браузере. Это действие возвращает пользователя на страницу категорий. В собственном приложении Android страница сведений о новостях отображается в том же экземпляре android.webkit.WebView где запускается приложение, за пределами HTML-страницы, на которой выполняется код приложения. Нажатие кнопки «Назад» на устройстве возвращает пользователя на страницу «Категории».

Диаграмма на рисунке 5 суммирует модель потока между страницами в нашем приложении новостей:

Новости подробно

Соблюдайте вращающийся значок во время определенных переходов. Это указывает на то, что страница прогресса показывается пользователю во время перехода. Страница прогресса полезна для предоставления пользователю обратной связи о том, что запрос обрабатывается. Обратите внимание, что страница перехода при переходе от News к News Detail отображается только в собственном приложении Android, а не в веб-приложении. (Более подробно об этом будет рассказано в части 3 «Изменения в index.html».)


Давайте поговорим о том, как запросы и ответы обрабатываются в веб-приложении. Существует одна HTML-страница, которая содержит пользовательский интерфейс и код обработки событий для приложения News, которая называется index.html . Этот файл загружается в мобильный браузер пользователя с веб-сервера (для нашего тестирования мы использовали веб-сервер Apache 2.2). Действия страницы «Получить категорию» и «Выбрать категорию» включают запросы AJAX для получения информации о новостях от Yahoo! URL сервера новостей, http://rss.news.yahoo.com/ . Из-за ограничения AJAX-запросов из одного источника браузер не может отправлять эти запросы непосредственно в Yahoo! Новостной сервер. В качестве bridge.php мы используем файл PHP на нашем веб-сервере с именем bridge.php , который отправляет эти запросы в Yahoo! Сервер новостей от имени браузера и ретранслирует ответ обратно. С другой стороны, действие страницы News Detail включает в себя регулярный HTTP-запрос GET к Yahoo! Новостной сервер. По этой причине bridge.php не нужен.

Модель запроса / ответа

С точки зрения модели запрос / ответ нативное Android-приложение отличается от веб-приложения в двух отношениях. Во-первых, ему не нужен bridge.php . Это связано с тем, что при упаковке в виде части собственного приложения Android HTML-страница, работающая в android.webkit.WebView , не подвергается ограничениям одного и того же происхождения при выполнении вызовов AJAX. Во-вторых, в нативном приложении Android действие News Detail представляет собой вызов AJAX, а не обычный HTTP-запрос GET. Мы обсудим это далее в части 3 «Изменения в index.html».


«Страница» в платформе jQuery Mobile может быть отдельной страницей или локальной внутренней связанной страницей внутри страницы. Страница контейнера будет включать одну или несколько страниц содержимого. Можно отображать / скрывать контентные страницы выборочно. Как упоминалось ранее, наше веб-приложение состоит из одной HTML-страницы с именем index.html которая содержит весь пользовательский интерфейс и код обработки событий. Мы определяем нашу страницу контейнера следующим образом:

1
2
3
4
<!— Container page —>
<div data-role=»page» data-theme=»b» id=»containerPage»>
   … <!— Content pages will go here —>
</div>

Атрибут data-theme тега div контейнера имеет значение b . Атрибут data-theme позволяет нам выбирать из доступных стилей jQuery Mobile:

1
<div data-role=»page» data-theme=»b» id=»page1″>

Тема по умолчанию имеет различные образцы цветов с именами a, b, c, d, e , каждый из которых обеспечивает согласованный набор цветов для различных элементов на странице. Для нашего приложения мы выбрали цвет, соответствующий b .

Страницы содержимого Категории, Выбор категории и Новости будут содержаться внутри страницы контейнера. Страница контента обычно имеет верхний колонтитул, область контента и нижний колонтитул, каждый из которых определен в теге div . Значение атрибута data-role в теге div определяет роль тега.

  • Чтобы определить заголовок, используйте <div ... data-role="header" ... >
  • Чтобы определить область содержимого, используйте <div ... data-role="content" ... >
  • Чтобы определить нижний колонтитул, используйте <div ... data-role="footer" ... >

Давайте теперь посмотрим на различные страницы контента в нашем приложении.

категории
01
02
03
04
05
06
07
08
09
10
11
12
13
<!— Categories —>
<div data-role=»header» id=»hdrCategories» data-nobackbtn=»true»>
   <h1>Categories</h1>
   <a id=»buttonAddCategory» data-icon=»plus» class=»ui-btn-left» href=»»
      data-role=»button» data-inline=»true»>Add</a>
</div>
 
<div data-role=»content» id=»contentCategories»>
   <ul data-role=»listview» data-split-icon=»delete» data-split-theme=»d»
      id=»currentNews»></ul>
</div>
 
<div data-role=»footer» id=»ftrCategories»></div>

В разделе заголовка data-nobackbtn="true" внимание на data-nobackbtn="true" . По умолчанию фреймворк jQuery Mobile будет включать кнопку «Назад» в разделе заголовка. Благодаря явной установке этого атрибута, как указано выше, мы не используем кнопку «Назад». Вместо этого мы добавляем кнопку «Добавить» в заголовок, используя <a id="buttonAddCategory" ...> . Поскольку значение атрибута data-icon равно plus , кнопка будет иметь знак плюс. Кроме того, class="ui-btn-left" гарантирует, что кнопка будет размещена с левой стороны заголовка. Мы не хотим ничего включать в раздел нижнего колонтитула, и поэтому div для нижнего колонтитула пуст. В результате в разделе нижнего колонтитула будет отображаться только тонкая горизонтальная линия.

Область содержимого имеет так называемый разделенный список jQuery Mobile. Как показано на рисунке 1, на котором показана страница «Категории», каждый элемент списка состоит из раздела слева с текстом и другого раздела справа с кнопкой, следовательно, «split». Атрибуты data-split-icon и data-split-theme определяют список как разделенный список. Обратите внимание, что платформа jQuery Mobile имеет возможность форматировать разделенные разделы различными способами. Например, вы можете разместить значки в текстовом разделе, что означает, что вместо кнопки удаления справа вы можете выбрать другой значок. В нашем приложении Новости каждый элемент списка будет соответствовать определенной категории новостей. Элементы списка будут построены динамически на основе выбора пользователя. Изначально список пуст.

Выбор категории
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<!— Category Selection —>
<div data-role=»header» id=»hdrSelect» data-nobackbtn=»true»>
  <h1>Select</h1>
</div>
 
<div data-role=»content» id=»contentSelect»>
  <form id=»form1″>
    <div id=»categoryDiv» data-role=»fieldcontain»>
      <select id=»category» tabindex=»2″>
        <option value=»>Select a Category</option>
        <option value=’topstories’>Top Stories</option>
        <option value=’us’>US</option>
        <option value=’world’>World</option>
        <option value=’politics’>Politics</option>
        …
      </select>
    </div>
    <a id=»buttonGetCategory» href=»» data-role=»button» data-inline=»true»>Get Category</a>
  </form>
</div>
 
<div data-role=»footer» id=»ftrSelect»></div>

На странице выбора категории в области содержимого есть форма, позволяющая пользователю выбрать и добавить категорию новостей. Категории новостей являются подмножеством категорий в Yahoo! Новости, перечисленные в http://news.yahoo.com/rss . Выбор категории обрабатывается, когда пользователь нажимает кнопку с id="buttonGetCategory" .

Обратите внимание, что кнопки «Назад» нет, а нижний колонтитул пуст.

Новости
01
02
03
04
05
06
07
08
09
10
11
12
<!— News —>
<div data-role=»header» id=»hdrNews» data-nobackbtn=»true»>
  <h1>News</h1>
  <a id=»buttonHdrShowCategories» data-icon=»arrow-l» class=»ui-btn-left» href=»» data-role=»button» data-inline=»true»>Back</a>
</div>
 
<div data-role=»content» id=»contentNews»></div>
 
<div data-role=»footer» id=»ftrNews»>
  <a id=»buttonFtrShowCategories» data-icon=»arrow-l» class=»ui-btn-left» href=»»
    data-role=»button» data-inline=»true»>Back to News Categories</a>
</div>

На этой странице область содержимого будет динамически заполняться всеми новостями, связанными с категорией, на основе выбора пользователя. Изначально область содержимого пуста. В разделе заголовка есть кнопка возврата. Однако вместо того, чтобы полагаться на обратное действие по умолчанию в jQuery Mobile, мы реализуем это действие через обработчик событий. Поэтому мы явно определяем кнопку с id="buttonHdrShowCategories" (код обработчика события для кнопки будет рассмотрен в части 2 «Переход на страницу категорий со страницы новостей»). Атрибут data-icon="arrow-l" использует встроенный значок jQuery Mobile, предназначенный для кнопок возврата. Доступные значки кнопок jQuery Mobile см. По адресу http://jquerymobile.com/demos/1.0a2/#docs/buttons/buttons-icons.html . На этой странице у нас также есть кнопка «Назад» в нижнем колонтитуле. Это связано с тем, что страница обычно бывает длинной и пользователю необходимо прокрутить страницу вниз, чтобы просмотреть все новости. Мы хотим, чтобы пользователь мог вернуться с нижней части страницы без необходимости прокрутки до самого верха. Обработчики событий для верхней и нижней кнопок назад будут идентичны.

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

01
02
03
04
05
06
07
08
09
10
11
<!— Progress —>
<div data-role=»header» id=»hdrProgress» data-nobackbtn=»true»>
    <h1>Processing…</h1>
</div>
 
<div data-role=»content» id=»contentProgress»>
    <div align=»CENTER»><h4>Please wait.</h4></div>
    <div align=»CENTER»><img id=»spin» src=»img/wait.gif»/></div>
</div>
 
<div data-role=»footer» id=»ftrProgress»></div>

Содержание страницы с подробностями новостей предоставлено Yahoo! URL новостей. Как эта страница отображается, описано в части 2 «Переход на страницу сведений о новостях со страницы новостей».

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<script>
  …
  var hdrCategoriesVar = $(‘#hdrCategories’);
  var contentCategoriesVar = $(‘#contentCategories’);
  var ftrCategoriesVar = $(‘#ftrCategories’);
   
  var hdrSelectVar = $(‘#hdrSelect’);
  var contentSelectVar = $(‘#contentSelect’);
  var ftrSelectVar = $(‘#ftrSelect’);
   
  var hdrProgressVar = $(‘#hdrProgress’);
  var contentProgressVar = $(‘#contentProgress’);
  var ftrProgressVar = $(‘#ftrProgress’);
   
  var hdrNewsVar = $(‘#hdrNews’);
  var contentNewsVar = $(‘#contentNews’);
  var ftrNewsVar = $(‘#ftrNews’);
  …
</script>

Чтобы скрыть страницу, мы вызываем функцию jQuery hide() переменных заголовка, содержимого и нижнего колонтитула этой страницы. Например, чтобы скрыть страницу категорий:

1
2
3
4
5
function hideCategories(){
   hdrCategoriesVar.hide();
   contentCategoriesVar.hide();
   ftrCategoriesVar.hide();
}

Аналогично, для страниц выбора категорий, новостей и прогресса у нас есть следующие функции «скрыть»:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
function hideSelect(){
   hdrSelectVar.hide();
   contentSelectVar.hide();
   ftrSelectVar.hide();
}
function hideNews(){
   hdrNewsVar.hide();
   contentNewsVar.hide();
   ftrNewsVar.hide();
}
function hideProgress(){
   hdrProgressVar.hide();
   contentProgressVar.hide();
   ftrProgressVar.hide();
}

Чтобы показать страницу, мы скрываем все остальные страницы и вызываем функцию jQuery show() переменных заголовка, содержимого и нижнего колонтитула этой страницы. Например, чтобы показать страницу категорий у нас есть следующая функция:

1
2
3
4
5
6
7
8
function showCategories(){
   hideSelect();
   hideProgress();
   hideNews();
   hdrCategoriesVar.show();
   contentCategoriesVar.show();
   ftrCategoriesVar.show();
}

Аналогично, для выбора категорий, новостей и страниц прогресса у нас есть следующие функции «показа»:

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
function showSelect(){
   hideCategories();
   hideProgress();
   hideNews();
   hdrSelectVar.show();
   contentSelectVar.show();
   ftrSelectVar.show();
}
function showNews(){
   hideCategories();
   hideSelect();
   hideProgress();
   hdrNewsVar.show();
   contentNewsVar.show();
   ftrNewsVar.show();
}
function showProgress(){
   hideCategories();
   hideSelect();
   hideNews();
   hdrProgressVar.show();
   contentProgressVar.show();
   ftrProgressVar.show();
}

Вместо одной HTML-страницы, содержащей весь код пользовательского интерфейса, мы могли бы организовать пользовательский интерфейс на несколько HTML-страниц. Для целей этого урока мы выбрали первый подход. В последнем случае см . Навигационную модель jQuery Mobile, в которой объясняется, как jQuery Mobile выполняет навигацию по страницам между различными физическими файлами.


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