Главная » Разработка для Android » ИСПОЛЬЗОВАНИЕ ДИАЛОГОВЫХ ОКОН ДЛЯ СБОРА ДАННЫХ, ВВОДИМЫХ ПОЛЬЗОВАТЕЛЕМ

0

Вопросы, рассматриваемые в этом часе:

•             работа с диалоговыми окнами деятельностей;

•             использование диалогового окна DatePickerDialog;

•             обработка и форматирование информации о дате;

•             построение пользовательских диалоговых окон.

В этом часе вы завершите работу над экраном с настройками приложения «Been There, Done That!», добавив несколько диалоговых окон Dialog в класс QuizSettingsActivity. Каждое диалоговое окно Dialog предназначено для сбора данных определенного типа, вводимых пользователем. Сначала вы добавите диалоговое окно Dialog, реализуемое классом DatePickerDialog и предназначенное для ввода даты, которое позволит пользователю указать его дату рождения, а затем вы создадите собственное диалоговое окно Dialog, чтобы предоставить пользователю возможность из­менять его пароль.

РАБОТА С ДИАЛОГОВЫМИ ОКНАМИ ДЕЯТЕЛЬНОСТЕЙ

Деятельность может использовать диалоговые окна Dialog для организации информации и обработки событий, возникающих в результате взаимодействия с пользователем. Напри­мер, деятельность может отобразить диалоговое окно с сообщением об ошибке или с предложением подтвердить некую операцию, например удаление некоторой информации. Использование диалоговых окон Dialog для решения простых задач позволяет сократить количество классов Activity в приложении.

Знакомство с различными типами диалоговых окон Dialog

В инструментарии Android SDK доступно несколько различных типов диалоговых окон Dialog, включая следующие:

•             Dialog — базовый класс для всех типов диалоговых окон Dialog (рис. 11.la).

•             AlertDialog — диалоговое окно с одним, двумя или тремя элементами Button (рис. 11.1 b).

•             Character PickerDialog – диалоговое окно, позволяющее выбрать символ с ударением, связанный с базовым символом (рис. 11.1c).

•             DatePickerDialog — диалоговое окно с элементом DatePicker (рис 11.1 d).

•             ProgressDialog — диалоговое окно с элементом ProgressBar, представляющим индикатор непрерывного хода выполнения процесса или индикатор хода выполнения процесса на основе значений (рис. 11.1e)

Рис. 11.1. Различные типы диалоговых окон Dialog, доступных в платформе Android

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

Отслеживание жизненного цикла диалогового окна деятельности

Каждое диалоговое окно Dialog должно быть определено внутри деятельности, в которой используется это окно. Отдельное диалоговое окно Dialog может открываться как едино­жды, так и использоваться регулярно. Понимание того, как деятельность управляет жиз­ненным циклом диалогового окна Dialog, имеет решающее значение для правильной реа­лизации диалогового окна Dialog. Давайте рассмотрим ключевые методы, которые должны использования деятельностью для управления диалоговым окном Dialog:

•            Метод showDialog () применяется для отображения диалогового окна Dialog.

•             Метод dismissDialog() используется для прекращения отображения диалогового окна Dialog на экране. Диалоговое окно Dialog продолжает оставаться в пуле диалоговых окон Dialog данной деятельности. При повторном отображении диалогового окна Dialog на экране с применением метода showDialog () будет использована кэшированная версия этого окна.

• Метод removeDialog () применяется для удаления диалогового окна Dialog из пула диалоговых окон Dialog данной деятельности. Диалоговое окно Dialog больше не будет доступно для дальнейшего использования. При повторном вызове метода showDialog () диалоговое окно Dialog необходимо создавать снова.

ОПРЕДЕЛЕНИЕ ДИАЛОГОВОГО ОКНА

Диалоговое окно, используемое в деятельности, должно быть определено заранее. Каждое диалоговое окно Dialog имеет свой идентификатор (целое число). При вызове метода showDialog () вы передаете этот идентификатор диалогового окна Dialog в качестве параметра данного метода. После этого происходит вызов метода onCreateDialog () , который возвращает экземпляр диалогового окна подходящего типа.

Вы должны переопределить метод onCreateDialog () деятельности и вернуть экзем­пляр подходящего диалогового окна в соответствии с заданным идентификатором. Если в деятельности используется несколько диалоговых окон Dialog, в методе onCreateDialog () может применяться инструкция switch для возврата экземпляра подходящего диалогового окна Dialog на основании переданного параметра — идентифи­катора диалогового окна Dialog.

ИНИЦИАЛИЗАЦИЯ ДИАЛОГОВОГО ОКНА

Поскольку диалоговое окно Dialog может сохраняться в пуле диалоговых окон Dialog дея­тельности, существенное значение может иметь возможность повторной инициализации диалогового окна при каждом его отображении, а не только при создании. С этой целью вы можете переопределить метод onPrepareDialog () деятельности.

В то время как метод onCreateDialog () может быть вызван лишь единожды для инициализации диалогового окна при его создании, метод onPrepareDialog () вызы­вается каждый раз при вызове метода showDialoq(), предоставляя деятельности воз­можность выполнить повторную инициализацию диалогового окна всякий раз, когда это окно показывается пользователю.

ОТОБРАЖЕНИЕ ДИАЛОГОВОГО ОКНА

Вы можете отобразить любое диалоговое окно, определенное в деятельности, вызвав ме­тод showDialog () этой деятельности и передай в него существующий идентификатор диалогового окна Dialog — идентификатор, который будет распознан методом

onCreateDialog() .

СОКРЫТИЕ ДИАЛОГОВОГО ОКНА

Для большинства типов диалоговых окон Dialog определены условия, при которых эти диалоговые окна будут автоматически скрыты. Тем не менее, если вы хотите самостоя­тельно скрыть диалоговое окно, вы можете просто вызвать метод dismissDialog () и передать в него идентификатор скрываемого диалогового окна Dialog.

УДАЛЕНИЕ ДИАЛОГОВОГО ОКНА

Сокрытие диалогового окна Dialog не приводит к уничтожению этого окна. При повтор­ном отображении диалогового окна используется его кэшированное содержимое. Если вы хотите, чтобы деятельность удалила диалоговое окно и в дальнейшем не использовала его, вызовите метод removeDialog () и передайте в него существующий идентификатор диалогового окна Dialog.

ИСПОЛЬЗОВАНИЕ ДИАЛОГОВОГО ОКНА DATEPICKERDIALOG

Теперь вы должны добавить диалоговое окно Dialog в класс QuizSettingsActivity. В частности, вы должны добавить диалоговое окно DatePickerDialog, которое предназначено для ввода даты рождения пользователя. Добав­ление диалогового окна DatePickerDialog в класс QuizSettingsActivity включает несколько шагов.

1.                                  Определить уникальный идентификатор для диалогового окна в классе деятельности.

2.                                 Реализовать метод onCreateDialog() деятельности, который будет возвращать экземпляр диалогового окна DatePickerDialog при указании уникального идентификатора, определенного на шаге 1.

3.                                 Реализовать метод onPrepareDialog() деятельности, который будет инициализировать диалоговое окно DatePickerDialog с использованием выбранной даты рождения или текущей даты.

4.                                  Отобразить диалоговое окно DatePickerDialog при помощи метода showDialog() , передав в него уникальный идентификатор диалогового окна Dialog.

Добавление диалогового окна DatePickerDialog в класс QuizSettingsActivity

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

static final int DATE_DIALOG_ID = 0;

Затем вам нужно реализовать метод onCreateDialog() класса QuizSettingsActivity и включить инструкцию case для нового идентификатора диалогового окна Dialog:

@Override

protected Dialog onCreateDialog(int id) { switch (id) { case DATE_DIALOG_ID:

// TODO: Return a DatePickerDialog here

Using DatePickerDialog 185 }

return null;

}

Теперь давайте подробно рассмотрим, как создать экземпляр диалогового окна DatePickerDialog. Внутри инструкции switch для идентификатора date_ dialog_id вы должны вернуть экземпляр диалогового окна DatePickerDialog для его последующего отображения. Конструктор диалогового окна DatePickerDialog имеет параметр

DatePickerDialog.OnDateSetListener, используя который, вы можете опреде­лить реализацию метода onDateSet (), вызываемого в тот момент, когда пользователь выберет свою дату рождения, благодаря чему вы сможете сохранить эту дату в экземпляре класса SharedPreferences:

DatePickerDialog dateDialog = new DatePickerDialog(this,

new DatePickerDialog.OnDateSetListener() {

public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { Time dateOfBirth = new Time();

dateOfBirth.set(dayOfMonth, monthOfYear, year); long dtDob = dateOfBirth.toMillis(true); dob.setText(DateFormat

.format("MMMM dd, yyyy", dtDob)); Editor editor = mGameSettings.edit(); editor.putLong(GAME_PREFERENCES_DOB, dtDob); editor.commit();

}

}, 0, 0, 0);

Элемент DatePicker состоит из трех отдельных элементов для ввода месяца, дня и года. Таким образом, чтобы создать экземпляр диалогового окна DatePickerDialog, вы должны указать значения для всех этих элементов. Поскольку диалоговое окно DatePickerDialog может отображаться произвольное число раз, нет необходимости инициализировать дату, отображаемую в этом диалоговом окне, в методе onCreateDialog () , поэтому для инициализации используются значения по умолчанию (три нуля). Наконец, вы возвра­щаете новый экземпляр диалогового окна DatePickerDialog, созданный в инструкции switch метода onCreateDialog():

return dateDialog;

Инициализация диалогового окна DatePickerDialog

Диалоговое окно DatePickerDialog должно инициализироваться всякий раз, когда оно отображается на экране, поэтому вы переопределяете метод onPrepareDialog(), чтобы установить для элемента DatePicker либо сегодняшнюю дату, либо дату рож­дения пользователя, сохраненную в настройках игры.

ВНИМАНИЕ! _____________________________________________________________

Чтобы получить текущую дату на устройстве, вы можете использовать класс Calendar. Класс Calendar имеет отдельные поля для каждой «части» даты — дня, месяца и года. Вы можете использовать эту возможность класса Calendar, чтобы установить опреде­ленную дату в диалоговом окне DatePickerDialog.

В метод onPrepareDialog() передается как идентификатор диалогового окна Dialog, так и экземпляр диалогового окна Dialog, поэтому при необходимости вы можете изменить этот экземпляр. Например, в данном случае вы должны обновить дату, отобра­жаемую в диалоговом окне DatePickerDialog, поэтому вы используете метод

updateDate() :

@Override

protected void onPrepareDialog(int id, Dialog dialog) { super.onPrepareDialog(id, dialog); switch (id) { case DATE_DIALOG_ID:

// Handle any DatePickerDialog initialization here DatePickerDialog dateDialog = (DatePickerDialog) dialog; int iDay, iMonth, iYear; // Check for date of birth preference if (mGameSettings.contains(GAME_PREFERENCES_DOB)) { // Retrieve Birth date setting from preferences long msBirthDate =

mGameSettings.getLong(GAME_PREFERENCES_DOB, 0); Time dateOfBirth = new Time(); dateOfBirth.set(msBirthDate); iDay = dateOfBirth.monthDay; iMonth = dateOfBirth.month; iYear = dateOfBirth.year; } else {

Calendar cal = Calendar.getInstance(); // Today’s date fields

iDay = cal.get(Calendar. DAY_OF_MONTH); iMonth = cal.get(Calendar. MONTH); iYear = cal.get(Calendar.YEAR);

}

// Set the date in the DatePicker to the date of birth OR to the

// current date

dateDialog.updateDate(iYear, iMonth, iDay); return;

}

}

Отображение диалогового окна DatePickerDialog

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

Вы зарегистрировали обработчик событий нажатий для элемента с именем Button_DOB, и в настоящий момент в этом обработчике событий вызывается метод класса Toast. Теперь вы можете изменить код обработчика, чтобы вызвать метод showDialog () для отобра­жения диалогового окна DatePickerDialog, изображенного на рис. 11.2:

Button pickDate = (Button) findViewById(R.id.Button DOB); pickDate.setOnClickListener(new View.OnClickListener() { public void onClick(View v) {

showDialog( DATE_DIALOG_ID);

}

});

Рис. 11.5. Дизайн-макет диалогового окна для ввода пароля приложения «Been There, Done That!»

На рис. 11.5 изображен дизайн-макет диалогового окна для ввода пароля.

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

РЕАЛИЗАЦИЯ МАКЕТА ДИАЛОГОВОГО ОКНА ДЛЯ ВВОДА ПАРОЛЯ

Теперь настало время реализовать новый макет, который будет использован в диалоговом окне для ввода пароля. Сначала вы создадите новый файл ресурса макета с именем password_dialog.xml. Этот файл макета определяет пользовательский интерфейс диалого­вого окна. Чтобы создать этот файл, выполните следующие шаги:

Откройте редактор ресурсов среды разработки Eclipse и добавьте в проект новый файл с именем /res/layout/password_dialog.xml.

Добавьте элемент-контейнер LinearLayout. Присвойте его атрибуту id значение root, а атрибуту orientation — значение vertical. Атрибутам layout_width и layout_height присвойте значение fill_parent. Все остальные элементы будут до­бавлены внутрь этого элемента-контейнера LinearLayout.

Добавьте элемент TextView для отображения строки «Password» (Пароль). Затем до­бавьте элемент EditText и присвойте его атрибуту id знамение EditText_Pwdl, ат­рибуту maxLines — значение 1, а атрибуту inputType — значение textPassword.

Добавьте еще один элемент TextView для отображения строки «Password (Again)» (Па­роль (подтверждение)). Затем добавьте еще один элемент EditText и присвойте его ат­рибуту id значение EditText_Pwd2, атрибуту maxLines — значение 1, а атрибуту

inputType — значение textPassword.

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

Теперь сохраните файл макета password_.dialog.xml.

ДОБАВЛЕНИЕ ДИАЛОГОВОГО ОКНА ДЛЯ ВВОДА ПАРОЛЯ В КЛАСС QUIZSETTINGSACTIVITY

Чтобы создать пользовательское диалоговое окно AlertDialog, вы сначала должны объя­вить уникальный идентификатор, представляющий это диалоговое окно, как показано ниже:

static final int PASSWORD_DIALOG_ID = 1;

Затем вам нужно обновить метод onCreateDialog() класса QuizSettingsActivity, добавив инструкцию case для нового идентификатора диало­гового окна Dialog:

case PASSWORD_DIALOG_ID: // Build Dialog // Return Dialog

Теперь давайте подробно рассмотрим процесс создания диалогового окна для ввода па­роля. Вы начнете с наполнения элемента View созданным макетом (т. е. загрузки макета в этот элемент):

LayoutInflater inflater = (LayoutInflater)

getSystemService(Context.LAYOUT_INFLATER_SERVICE); final View layout =

inflater.inflate(R.layout.password_dialog, (ViewGroup) findViewById(R.id.root));

Чтобы загрузить файл макета password_dialog.xml н элемент View, вы должны получить экземпляр класса LayoutInflater и кием пытать метод atop, передан в качестве пара­метра идентификатор ресурса макета, а также идентификатор корневого элемента макета (в данном случае — элемент-контейнер LinearLayout с именем root, содержащий остальные элементы диалогового окна).

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

Например, чтобы получить экземпляр элемента с именем EditText_Pwd1 из перемен­ной типа View с именем layout, можно использовать метод findViewByid (), как по­казано в следующем коде:

final EditText p1 =

(EditText) layout.findViewById(R.id.EditText_Pwd1); final EditText p2 =

(EditText) layout.findViewById(R.id.EditText_Pwd2);

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

Например, вы можете зарегистрировать слушателя для событий изменения текста во вто­ром элементе EditText, используя класс TextWatcher, и сравнивать содержимое этого поля ввода с содержимым первого элемента EditText. После этого вы можете отобразить результат сравнения паролей в третьем элементе TextView с именем TextView_PwdProblem, который мы создали ранее:

final TextView error =

(TextView) layout.findViewById(R.id.TextView PwdProblem); p2.addTextChangedListener(new TextWatcher() { @Override

public void afterTextChanged(Editable s) {

String strPassl = p1.getText().toString(); String strPass2 = p2.getText().toString(); if (strPass1.equals(strPass2)) { error.setText(R.string.settings pwd equal); } else {

error.setText(R.string.settings pwd not equal);

}

}

// … other required overrides do nothing

});

Класс TextWatcher имеет несколько методов, которые нужно реализовать. Тем не менее, нас больше всего интересует метод afterTextChanged () .

Теперь, когда вы заполнили элемент View ресурсом макета и настроили его для дальней­шего использования, вы можете присоединить его к диалоговому окну AlertDialog. Для этого используется класс AlertDialog.Builder:

AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setView(layout);

builder.setTitle(R.string.settings button pwd);

Сначала вы устанавливаете в качестве элемента-представления экземпляра класса AlertDialog.Builder загруженный вами макет. Затем вы устанавливаете заголовок диалогового окна Dialog при помощи метода setTitle ( ) .

Ваше диалоговое окно будет иметь два элемента Button: кнопку положительного ответа (ОК) и кнопку отрицательного ответа (Cancel). Поскольку вы не хотите, чтобы это диало­говое окно кэшировалось для дальнейшего использования деятельностью, в обоих обра­ботчиках событий для элементов Button должен вызываться метод removeDialog () , который уничтожает диалоговое окно:

QuizSettingsActivity.this

.removeDialog(PASSWORD_DIALOG_ID);

Кнопка положительного ответа (ОК) подразумевает некоторую обработку данных. Когда пользователь нажимает на нее, вам нужно извлечь текст паролей из элементов EditText, сравнить полученные значения и, если две строки совпадают, сохранить новый пароль в настройках приложения:

builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) { TextView passwordlnfo =

(TextView) findViewById(R.id.TextView Password Info); String strPasswordl = p1.getText().toString(); String strPassword2 = p2.getText().toString(); if (strPassword1.equals(strPassword2)) { Editor editor = mGameSettings.edit(); editor.putString(GAME_PREFERENCES_PASSWORD,

strPasswordl); editor.commit();

passwordInfo.setText(R.string.settings pwd set); } else {

Log. d (DEBUG_TAG, "Passwords do not match. "

+ "Not saving. Keeping old password (if set).");

}

QuizSettingsActivity. this .removeDialog(PASSWORD_DIALOG_ID);

}

});

Кнопка отрицательного ответа, Cancel, просто возвращает пользователя на основной экран с настройками. Вы настраиваете поведение кнопки отрицательного ответа при помощи метода setNegativeButton () класса Builder:

builder.setNegativeButton(android.R.string. cancel, new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int whichButton) { QuizSettingsActivity. this

.removeDialog(PASSWORD_DIALOG_ID);

}

});

Когда ваше диалоговое окно будет полностью сконфигурировано при помощи класса Builder, вы вызываете метод create () , чтобы создать и вернуть экземпляр пользо­вательского диалогового окна AlertDialog:

AlertDialog passwordDialog = builder.create(); return passwordDialog;

ОТОБРАЖЕНИЕ ПОЛЬЗОВАТЕЛЬСКОГО ДИАЛОГОВОГО ОКНА ДЛЯ ВВОДА ПАРОЛЯ

Пользовательское диалоговое окно, как, например, ваше диалоговое окно для ввода пароля, отображается таким же способом, что и обычное диалоговое окно, — при помощи метода showDialog() деятельности. На экране с настройками приложения «Been There, Done That!» пользователь выбывает открытие диалогового окна для ввода пароля, нажимая на элемент Button с именем Button_Password. Таким образом, вы можете зарегистрировать обработчик событий нажатия для этого элемента Button и отображать диалоговое окно для ввода пароля соответствующим образом:

Button setPassword = (Button) findViewById(R.id.Button Password); setPassword.setOnClickListener(new View.OnClickListener() { public void onClick(View v) {

showDialog(PASSWORD_DIALOG_ID);

}

});

На рис. 11.6 изображен готовый экран с настройками, включая элементы для отображения диалоговых окон Dialog.


Been There, Dor

ф. 1

Nickname: "

Email: ш Password:

e That!

stings . Щ

*

i * ‘ *

‘ /

 

Password Set

pirtti Date:

>t

?

?* .. . * January 21, 13BB

Gender:

? v : \ .

 

bpmJ

Рис. 11.6. Готовый экран с настройками приложения «Been There, Done That!»

ИТОГИ

В этом часе вы ознакомились с тем, как деятельность может использовать диалоговые окна Dialog для упрощения функциональности экрана и его макета на примере экрана с настройками приложения «Been There, Done That!». Диалоговое окно может использо­ваться для отображения необходимой информации и виде всплывающего окна. Сущест­вуют стандартные типы диалоговых окон Dialog для ввода даты, времени и специальных символов, а также вспомогательные диалоговые окна Dialog для отображения индикато­ров хода выполнения процесса или предупреждений. Кроме того, вы также можете созда­вать пользовательские диалоговые окна Dialog.

ВОПРОСЫ И ОТВЕТЫ

Вопрос: Каким образом сохраняется информация о диалоговых окнах в деятельности?

Ответ: Каждая деятельность имеет пул используемых диалоговых окон Dialog, и именно из этого пула будет извлекаться диалоговое окно Dialog при его повторном отображении. По существу, диалоговые окна отображаются при помощи метода showDialog (), после чего они помещаются в пул. При закрытии диалоговое окно остается в пуле до тех пор, пока не будет уничтожена деятельность или пока не будет явно вызван метод removeDialog() .

Вопрос: Как определить, из какой деятельности было вызвано диалоговое окно Dialog?

Ответ: Чтобы определить родительскую деятельность определенного диалогового окна Dialog, вы можете использовать метод getOwnerActivity () класса Dialog.

ПРАКТИКУМ Контрольные вопросы

1.                     Какой класс может быть использован внутри деятельности для создания всплывающих окон?

A.                   Popup.

B.                    ActivityWindow.

C.                   Dialog.

2.                     Верно ли что? Вы можете использовать одно и то же диалоговое окно многократно, если макет этого диалогового окна не изменяется.

3.                     Верно ли что? Только определенные макеты могут быть использованы для таких диалоговых окон, как Alert и ContinueOrCancel.

Ответы

1.                     В. Класс Dialog и производные от него классы могут быть использованы внутри деятельности для создания всплывающих окон при помощи методой

onCreateDialog() иshowDialog().

2.                     Верно. Но для отображения друг их данных в диалоговом окне вам потре­буется переопределить внутри деятельности метод onPrepareDialog () .

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

Литература: Дэрси JI., Android за 24 часа. Программирование приложений под операционную систему Google/ ДэрсиЛ., КондерШ. — М.: Рид Групп, 2011. — 464 с. — (Профессиональные компьютерные книги). ISBN 978-5-4252-0318-2

По теме:

  • Комментарии