В этом уроке:

- работаем с DialogFragment

 

Продолжаем рассматривать наследников Fragment. DialogFragment – отличается от обычного фрагмента тем, что отображается как диалог и имеет соответствующие методы.

Построить диалог можно двумя способами: используя свой layout-файл и через AlertDialog.Builder. Нарисуем приложение, которое будет вызывать два диалога, построенных разными способами.

 

Создадим проект:

Project name: P1101_DialogFragment
Build Target: Android 4.1
Application name: DialogFragment
Package name: ru.startandroid.develop.p1101dialogfragment
Create Activity: MainActivity

 

Добавим строки в strings.xml:

<string name="dialog_1">Dialog 1</string>
<string name="dialog_2">Dialog 2</string>
<string name="message_text">Text of your message</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="maybe">Maybe</string>

Мы будем создавать два диалога, соответственно нам понадобятся два фрагмента.

 

Создадим layout-файл для первого фрагмента.

dialog1.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="wrap_content"
	android:layout_height="match_parent"
	android:orientation="vertical">
	<TextView
		android:id="@+id/textView1"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="center"
		android:layout_margin="20dp"
		android:text="@string/message_text"
		android:textAppearance="?android:attr/textAppearanceLarge">
	</TextView>
	<LinearLayout
		android:layout_width="wrap_content"
		android:layout_height="wrap_content">
		<Button
			android:id="@+id/btnYes"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_margin="10dp"
			android:text="@string/yes">
		</Button>
		<Button
			android:id="@+id/btnNo"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_margin="10dp"
			android:text="@string/no">
		</Button>
		<Button
			android:id="@+id/btnMaybe"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_margin="10dp"
			android:text="@string/maybe">
		</Button>
	</LinearLayout>
</LinearLayout>

Так будет выглядеть наш диалог – текст сообщения и три кнопки.

 

Создаем класс Dialog1.java:

package ru.startandroid.develop.p1101dialogfragment;

import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;

public class Dialog1 extends DialogFragment implements OnClickListener {

  final String LOG_TAG = "myLogs";

  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    getDialog().setTitle("Title!");
    View v = inflater.inflate(R.layout.dialog1, null);
    v.findViewById(R.id.btnYes).setOnClickListener(this);
    v.findViewById(R.id.btnNo).setOnClickListener(this);
    v.findViewById(R.id.btnMaybe).setOnClickListener(this);
    return v;
  }

  public void onClick(View v) {
    Log.d(LOG_TAG, "Dialog 1: " + ((Button) v).getText());
    dismiss();
  }

  public void onDismiss(DialogInterface dialog) {
    super.onDismiss(dialog);
    Log.d(LOG_TAG, "Dialog 1: onDismiss");
  }

  public void onCancel(DialogInterface dialog) {
    super.onCancel(dialog);
    Log.d(LOG_TAG, "Dialog 1: onCancel");
  }
}

В onCreateView мы получаем объект Dialog с помощью метода getDialog и устанавливаем заголовок диалога. Далее мы создаем view из layout, находим в нем кнопки и ставим им текущий фрагмент в качестве обработчика.

В onClick выводим в лог текст нажатой кнопки и сами явно закрываем диалог методом dismiss.

Метод onDismiss срабатывает, когда диалог закрывается. Пишем об этом в лог.

Метод onCancel срабатывает, когда диалог отменяют кнопкой Назад. Пишем об этом в лог.

 

Создаем второй фрагмент. Здесь мы будем строить диалог с помощью билдера, поэтому layout-файл не понадобится. Создаем только класс Dialog2.java:

package ru.startandroid.develop.p1101dialogfragment;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.util.Log;

public class Dialog2 extends DialogFragment implements OnClickListener {

  final String LOG_TAG = "myLogs";

  public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder adb = new AlertDialog.Builder(getActivity())
        .setTitle("Title!").setPositiveButton(R.string.yes, this)
        .setNegativeButton(R.string.no, this)
        .setNeutralButton(R.string.maybe, this)
        .setMessage(R.string.message_text);
    return adb.create();
  }

  public void onClick(DialogInterface dialog, int which) {
    int i = 0;
    switch (which) {
    case Dialog.BUTTON_POSITIVE:
      i = R.string.yes;
      break;
    case Dialog.BUTTON_NEGATIVE:
      i = R.string.no;
      break;
    case Dialog.BUTTON_NEUTRAL:
      i = R.string.maybe;
      break;
    }
    if (i > 0)
      Log.d(LOG_TAG, "Dialog 2: " + getResources().getString(i));
  }

  public void onDismiss(DialogInterface dialog) {
    super.onDismiss(dialog);
    Log.d(LOG_TAG, "Dialog 2: onDismiss");
  }

  public void onCancel(DialogInterface dialog) {
    super.onCancel(dialog);
    Log.d(LOG_TAG, "Dialog 2: onCancel");
  }
}

Обычно для заполнения фрагмента содержимым мы использовали метод onCreateView. Для создания диалога с помощью билдера используется onCreateDialog. Создаем диалог с заголовком, сообщением и тремя кнопками. Обработчиком для кнопок назначаем текущий фрагмент.

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

Методы onDismiss и onCancel – это закрытие и отмена диалога, аналогично первому фрагменту.

 

Меняем layout-файл для MainActivity - main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:tools="http://schemas.android.com/tools"
	android:id="@+id/LinearLayout1"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical">
	<Button
		android:id="@+id/btnDlg1"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:onClick="onClick"
		android:text="@string/dialog_1">
	</Button>
	<Button
		android:id="@+id/btnDlg2"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:onClick="onClick"
		android:text="@string/dialog_2">
	</Button>
</LinearLayout>

Здесь только две кнопки.

 

Кодим MainActivity.java:

package ru.startandroid.develop.p1101dialogfragment;

import android.app.Activity;
import android.app.DialogFragment;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

  DialogFragment dlg1;
  DialogFragment dlg2;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    dlg1 = new Dialog1();
    dlg2 = new Dialog2();
  }

  public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btnDlg1:
      dlg1.show(getFragmentManager(), "dlg1");
      break;
    case R.id.btnDlg2:
      dlg2.show(getFragmentManager(), "dlg2");
      break;
    default:
      break;
    }

  }
}

Создаем диалоги и запускаем их методом show, который на вход требует FragmentManager и строку-тэг. Транзакция и коммит происходят внутри этого метода, нам об этом думать не надо.

Все сохраняем и запускаем приложение.

 

Жмем Dialog1

Отобразился наш простенький диалог.

Жмем какую-нибудь кнопку, например, Yes - диалог закрылся. Смотрим логи:

Dialog 1: Yes
Dialog 1: onDismiss

Все верно.

 

Снова запустим первый диалог и нажмем клавишу Назад (Back). Смотрим лог:

Dialog 1: onCancel
Dialog 1: onDismiss

Сработал onCancel – диалог был отменен, и onDismiss – диалог закрылся.

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

 

Запустим второй диалог – нажмем кнопку Dialog 2.

Отобразился стандартный сконструированный нами диалог. Жмем, например, No – диалог закрылся. В логах:

Dialog 2: No
Dialog 2: onDismiss

 

Снова запустим второй диалог и нажмем Назад. В логах:

Dialog 2: onCancel
Dialog 2: onDismiss

Все так же, как и в первом случае.

 

Еще несколько слов по теме.

Если вы не хотите, чтобы ваш диалог можно было закрыть кнопкой, используйте для вашего диалог-фрагмента метод setCancelable с параметром false.

Есть еще один вариант вызова диалога. Это метод show, но на вход он уже принимает не FragmentManager, а FragmentTransaction. В этом случае система также сама вызовет commit внутри show, но мы можем предварительно поместить в созданную нами транзакцию какие-либо еще операции или отправить ее в BackStack.

Вы можете использовать диалог-фрагменты, как обычные фрагменты и отображать их на Activity, а не в виде диалога. Но при этом будьте аккуратнее с использованием getDialog. Я так понял, что он возвращает null в этом случае.

Если AlertDialog.Builder вам незнаком, то посмотрите Урок 60 и несколько следующих за ним. Там достаточно подробно описано, как создавать различные диалоги.

 

На следующем уроке:

- работаем с PreferenceFragment
- используем Headers


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование



Похожие статьи


Последние статьи



Language

Система Orphus

Социальные сети

 

Telegram канал



Android чат в Telegram



Группа ВКонтакте



Страница в Facebook

Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal

Яндекс.Метрика