Сегодня мы продолжим экспериментировать с Android и напишем виджет, который будет считать количество оставшихся дней до определенного события. Я предполагаю, что у вас уже настроен SDK и среда разработки, если нет, то читайте первую часть повествования - Установка и настройка Android SDK. Первое приложение.
Определенным событием будет PyCon Ukaraine, который начнется 23.10.2010.
Создадим новый проект, все этапы описаны в предыдущем посте, в этот раз мы только поменяем имя на PyConWidget, и снимем отметку с Create Activity, у меня получилось так:
Project name: PyConWidget Build Target: [x] Android 2.1-update1 Application name: PyConWidget Package name: com.example.pyconwidget [ ] Create Activity: Min SDK Version: 7
Изображение с фоном для виджета и логотипом pycon'a можно найти в файле проекта, прикрепленного в конце поста.
Для начала опишем внешний вид виджета, за это отвечает файл /res/layout/main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/bg"> > <ImageView android:src="@drawable/pylogo" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="1dip" /> <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:textSize="17sp" android:gravity="center" android:textColor="@android:color/white" /> </LinearLayout>
У нас есть: главный layout (LinearLayout), с вертикальным расположением элементов и фоном (атрибут android:background); визуальный компонент ImageView, содержащий логотип; TextView - в котором будем выводить количество дней до pycon.
Файл /res/values/strings.xml содержит строчные константы: название виджета и текст, отображаемый по-умолчанию:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Loading</string> <string name="app_name">PyCon Widget</string> <string name="widget_name">PyCon Widget</string> </resources>
Создадим файл /res/xml/widget.xml, в котором опишем параметры виджета:
<?xml version="1.0" encoding="UTF-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="50dip" android:minHeight="50dip" android:updatePeriodMillis="86400000" android:initialLayout="@layout/main" />
В файле AndroidManifest.xml добавим тег receiver (внутрь тега application) который отвечает за Broadcast Receiver и указывает, что виджет будет реагировать на событие (intent) - APPWIDGET_UPDATE (т.е. обновляться). Также указываем на layout виджета:
... <receiver android:name=".PyConWidget" android:label="@string/widget_name"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" /> </receiver> ...
Осталось только реализовать логику виджета и добавить это все в обработчик события - обновление виджета.
package com.example.pyconwidget; import java.util.Date; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.widget.RemoteViews; import java.util.Calendar; import java.util.GregorianCalendar; public class PyConWidget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Date today = new Date(); Calendar calendar = new GregorianCalendar(2010, 9, 23); long days = (((calendar.getTimeInMillis() - today.getTime())/1000))/86400; String txt; if (days > 1) { txt = days + "\ndays"; } else if (days == 1) { txt = days + "\nday"; } else if (days == 0 || days == -1) { txt = "online"; } else { txt = "closed"; } RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.main); updateViews.setTextViewText(R.id.text, txt); appWidgetManager.updateAppWidget(appWidgetIds, updateViews); super.onUpdate(context, appWidgetManager, appWidgetIds); } }
Класс AppWidgetProvider является базовым для класса нашего виджета PyConWidget, мы переопределяем метод onUpdate, который вызывается при обновлении виджета. Для изменения параметров визуальных компонентов внутри виджетов используются объекты класса RemoteViews. После изменения текста внутри TextView мы говорим WidgetManager что надо бы обновить и сам виджет.
Скриншот виджета:
Виджет проверен на HTC Wildfire - все чудесно отображается! :)
Проект в Eclipse для приведенного виджета - pycon_widget.tar.gz
Apk файл с виджетом - PyConWidget.apk
Дополнительное чтиво