Поиск по сайту:

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

Ссылка на проект на гитхабе