Работа с PreferenceActivity в Android

22 июня 2010 г.

Введение

Что есть activity? Руководство разработчика дает нам следующее описание:
«Активити представляет собой визуальный пользовательский интерфейс для одного конкретного действия, который может предпринять пользователь». По сути, активити – это экран (страничка), позволяющая выполнить пользовательское действие: просмотреть текущее состояние, отредактировать свойства чего-нибудь, прочитать сообщение. Про редактирование каких-либо свойств мы сегодня и поговорим.
Часто нам приходится заполнять какие-либо формы. В одном маленьком проекте нам нужно было заполнять информацию о задаче, успех которой будет отслеживать пользователь. Первоначально мы сделали это просто накидав полей для ввода на экран. Выглядело это отвратительно, поля не были выровнены относительно друг друга ни по высоте, ни по ширине. Пользоваться было трудно и неприятно.
Чуть позже обнаружилось, что есть правильный способ реализовывать такие диалоги, и это – PreferenceActivity.

PreferenceActivity

Это класс-наследник Activity. Он позволяет редактировать так называемые свойства – preferences, которые задаются в xml-файле. На скриншоте видим четыре свойства – два текстовых, дату и флаг.

Чтобы описать такие свойства, xml должен быть приблизительно следующим:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/header_activity">
<EditTextPreference android:key="name"
android:persistent="false"
android:title="@string/activity_name"
android:dialogTitle="@string/activity_name" />
<EditTextPreference android:key="desc"
android:persistent="false"
android:title="@string/description"
android:dialogTitle="@string/description" />
<Preference android:key="time"
android:persistent="false"
android:title="@string/start_date"/>
<CheckBoxPreference android:key="hidden"
android:persistent="false"
android:title="@string/hidden"/>

У каждого свойства описывается заголовок, заголовок диалога, в котором будет происходить редактирование и признак сохранности – persistent. Если он будет выставлен в true, андройд будет хранить значения свойств в собственном хранилище, но нам это не нужно – приложение работает с базой и хранит все свои данные там.

Чтобы начать работу над своей Activity, нужно создать класс, наследующий PreferenceActivity:

public class EditActivityScreen extends PreferenceActivity
implements DatePickerDialog.OnDateSetListener{
…
}

Интерфейс OnDateSetListener нам понадобился, чтобы определить действие, которое мы будем выполнять по выбору пользователем даты.
Итак, пишем в onCreate():

addPreferencesFromResource(R.xml.activity_prefs);
activityNamePref = (EditTextPreference) findPreference("name");
activityNamePref.setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference p,
Object newValue) {
// Set the summary based on the new label.
p.setSummary((String) newValue);
return true;
}
});

Здесь activityNamePref – это член класса нашей активити типа EditTextPreference.
Первой строкой говорим, какой файл будет использоваться в качестве описания свойств. Дальше нужно создать класс-обработчик события сохранения нового значения в диалог редактирования свойства.
Но это все достаточно просто и понятно. Дальше начинается веселье.
Дело в том, что кроме самих свойств, мы хотим иметь внизу 2 кнопки – сохранения и отмены. Вся дальнейшая магия происходит за тем, чтобы эти кнопки туда поместить:

// Даем возможность кнопкам получать фокус.
getListView().setItemsCanFocus(true);

// Получаем лэйаут, потому что мы хотим его поменять
FrameLayout content = (FrameLayout) getWindow().getDecorView()
.findViewById(android.R.id.content);

// Берем лист вью – это то вью, где содержатся свойства.
ListView lv = getListView();
content.removeView(lv);

// Создаем новый лэйаут – он и будет содержимым
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);

// Параметры лэйаута.
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lp.weight = 1;
ll.addView(lv, lp);

// Навешиваем на него кнопки.
View v = LayoutInflater.from(this).inflate(
R.layout.edit_screen, ll);

Т.е. суть магии сводится к следующему: получить текущий список, убрать его с контента, засунуть на контент новый лэйаут, на который вернуть список и добавить к нему кнопки. Почему так нельзя сделать сразу с контентом не очень понятно.
С кнопками разобрались. Вы спросите, а как же диалог ввода даты? Ведь соответствующее свойство у нас описано как просто Preference.

Секрет в имплементации onPreferenceTreeClick:

@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) {
if (preference == startDatePref) {
new DatePickerDialog(this, this, year, monthOfYear, dayOfMonth).show();
}

return super.onPreferenceTreeClick(preferenceScreen, preference);
}

введенные пользователем.

Все, что осталось, это определить, что произойдет, когда пользователь закроет диалог кнопкой Set:

@Override
public void onDateSet(DatePicker datePicker, int i, int i1, int i2) {
year = i;
monthOfYear = i1;
dayOfMonth = i2;
updateDate();
}

private void updateDate() {
startDatePref.setSummary(
new StringBuilder()
// Month is 0 based so add 1
.append(year).append("-")
.append(monthOfYear+1).append("-")
.append(dayOfMonth).append(" "));
}

Заключение

Вот таким нехитрым образом можно создать свой PreferenceActivity. Все, что вам останется сделать – это написать код, сохраняющий информацию из Preference-членов класса туда, куда нужно вам. Сделать это просто, взяв getSummary() от каждого члена. Удачи в разработке!

Список литературы:
developer.android.com/guide/index.html — dev guide.
android.git.kernel.org/?p=platform/packages/apps/AlarmClock.git;a=tree;hb=HEAD – репозитарий будильника для андроид

Теги:
рубрика Android
  • Похожие статьи
  • Предыдущие из рубрики