Android DialogFragment
В этом уроке мы обсудим, что такое DialogFragments. Мы также увидим, чем они отличаются от диалогов, с помощью простого приложения для Android.
Android DialogFragments
DialogFragment — это служебный класс, расширяющий класс Fragment. Он является частью библиотеки поддержки версии 4 и используется для отображения наложенного модального окна в действии, которое плавает поверх остального содержимого. По сути, DialogFragment отображает диалоговое окно, но внутри фрагмента.
Google рекомендует использовать DialogFragment вместо простого построителя Alert Dialog в действии.
Почему так?
- Диалоговые фрагменты имеют собственные методы жизненного цикла. Таким образом, действие освобождается от обязанности сообщать диалогу, что делать.
- Больше никаких исключений IllegalStateException и утечек окон. Это было довольно распространенным явлением, когда действие уничтожалось, а диалоговое окно оповещения оставалось на месте.
Поскольку DialogFragment является фрагментом, он интегрируется в жизненный цикл активности и гарантирует, что то, что происходит в диалоговом окне, остается согласованным. Хорошей практикой является использование DialogFragments для создания диалогов в вашем приложении для Android. Ваш класс должен расширять DialogFragment, реализуя как минимум onCreateDialog
и/или onCreateView
. Вы можете создавать диалоги с помощью DialogFragment двумя способами:
onCreateDialog
. Здесь вы можете создать AlertDialog с помощью класса AlertDialog.Builder.onCreateView
. Здесь вы можете создать диалоговое окно, используя определенное пользовательское представление.
Чтобы создать DialogFragment, который показывает Dialog, нам нужно вызвать метод show() для экземпляра DialogFragment следующим образом:
MyDialogFragment dialogFragment = new MyDialogFragment();
FragmentTranscation ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
Мы можем установить любой тег в качестве второго аргумента show()
. Чтобы создать DialogFragment, который встраивает диалог во фрагмент, мы просто добавляем
фрагмент в макет фрейма, как мы делаем это с любым фрагментом.
Вы знаете? Вы также можете отображать пользовательские представления во фрагментах, а не только в диалогах.
При создании экземпляра класса DialogFragment. Методы вызываются в следующем порядке:
- при создании
- Диалоговое окно создания
- онкреатевиев
- онвиевкреатед
- при уничтожении
Передача данных в DialogFragment и из него
Чтобы передать данные классу DialogFragment, мы можем просто установить данные с помощью setArguments в экземпляре класса. Чтобы вернуть данные из DialogFragments в Activity/другой фрагмент, нам нужно создать собственный интерфейс. В следующем разделе мы создадим приложение для Android, которое выполняет следующие действия:
- Создает диалоговое окно Simple DialogFragment
- Диалоговый фрагмент, встроенный в действие.
- DialogFragment со стилем.
- DialogFragment, возвращающий данные
Структура проекта
Код
Код для класса activity_main.xml приведен ниже:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/btnEmbedDialogFragment"
android:layout_alignParentTop="true" />
<Button
android:id="@+id/btnEmbedDialogFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_above="@+id/btnDialogFragment"
android:text="EMBED DIALOG FRAGMENT" />
<Button
android:id="@+id/btnDialogFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="8dp"
android:text="SIMPLE DIALOG FRAGMENT" />
<Button
android:id="@+id/btnDialogFragmentFullScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnDialogFragment"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp"
android:text="DIALOG FRAGMENT FULL SCREEN" />
<Button
android:id="@+id/btnAlertDialogFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnDialogFragmentFullScreen"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp"
android:text="Alert Dialog Fragment" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnAlertDialogFragment"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Каждая из кнопок будет запускать отдельный тип DialogFragment. Макет xml для пользовательского представления для DialogFragment определен в файле fragment_sample_dialog.xml, как показано ниже:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Please enter your username and password" />
<EditText
android:id="@+id/inEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email Address"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/inPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword" />
<Button
android:id="@+id/btnDone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Done" />
</LinearLayout>
Таким образом, наш диалог будет отображать базовую форму входа. Код для MainActivity.java приведен ниже:
package com.journaldev.androiddialogfragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, MyDialogFragment.DialogListener {
Button btnEmbedDialogFragment, btnDialogFragment, btnDialogFragmentFullScreen, btnAlertDialogFragment;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
btnEmbedDialogFragment = findViewById(R.id.btnEmbedDialogFragment);
btnDialogFragment = findViewById(R.id.btnDialogFragment);
btnDialogFragmentFullScreen = findViewById(R.id.btnDialogFragmentFullScreen);
btnAlertDialogFragment = findViewById(R.id.btnAlertDialogFragment);
btnEmbedDialogFragment.setOnClickListener(this);
btnDialogFragment.setOnClickListener(this);
btnDialogFragmentFullScreen.setOnClickListener(this);
btnAlertDialogFragment.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnEmbedDialogFragment:
MyDialogFragment dialogFragment = new MyDialogFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frameLayout, dialogFragment);
ft.commit();
break;
case R.id.btnDialogFragment:
dialogFragment = new MyDialogFragment();
Bundle bundle = new Bundle();
bundle.putBoolean("notAlertDialog", true);
dialogFragment.setArguments(bundle);
ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
break;
case R.id.btnDialogFragmentFullScreen:
dialogFragment = new MyDialogFragment();
bundle = new Bundle();
bundle.putString("email", "xyz@gmail.com");
bundle.putBoolean("fullScreen", true);
bundle.putBoolean("notAlertDialog", true);
dialogFragment.setArguments(bundle);
ft = getSupportFragmentManager().beginTransaction();
prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
break;
case R.id.btnAlertDialogFragment:
dialogFragment = new MyDialogFragment();
ft = getSupportFragmentManager().beginTransaction();
prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
break;
}
}
@Override
public void onFinishEditDialog(String inputText) {
if (TextUtils.isEmpty(inputText)) {
textView.setText("Email was not entered");
} else
textView.setText("Email entered: " + inputText);
}
}
Приведенный выше класс реализует интерфейс MyDialogFragment.DialogListener
, который запускает метод onFinishEditDialog
всякий раз, когда нажимается кнопка DialogFragment. Он отображает данные, введенные в диалоговом окне действия. Код для класса MyDialogFragment.java приведен ниже:
package com.journaldev.androiddialogfragment;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
public class MyDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
if (getArguments() != null) {
if (getArguments().getBoolean("notAlertDialog")) {
return super.onCreateDialog(savedInstanceState);
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Alert Dialog");
builder.setMessage("Alert Dialog inside DialogFragment");
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
}
});
return builder.create();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_sample_dialog, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final EditText editText = view.findViewById(R.id.inEmail);
if (getArguments() != null && !TextUtils.isEmpty(getArguments().getString("email")))
editText.setText(getArguments().getString("email"));
Button btnDone = view.findViewById(R.id.btnDone);
btnDone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DialogListener dialogListener = (DialogListener) getActivity();
dialogListener.onFinishEditDialog(editText.getText().toString());
dismiss();
}
});
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("API123", "onCreate");
boolean setFullScreen = false;
if (getArguments() != null) {
setFullScreen = getArguments().getBoolean("fullScreen");
}
if (setFullScreen)
setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
public interface DialogListener {
void onFinishEditDialog(String inputText);
}
}
AndroidDialogFragment
Ссылка на проект на гитхабе