Android DialogFragment

Filed Under: Android

In this tutorial, we’ll be discussing what are DialogFragments. We’ll see how they are different from the Dialogs too with the help of a simple android application.

Android DialogFragments

DialogFragment is a utility class which extends the Fragment class. It is a part of the v4 support library and is used to display an overlay modal window within an activity that floats on top of the rest of the content.

Essentially a DialogFragment displays a Dialog but inside a Fragment.

Google recommends that we use DialogFragment instead of a simple Alert Dialog builder in the activity.

Why so?

  • DialogFragments have their own lifecycle methods. So the Activity is free from the responsibility of telling the Dialog what to do.
  • No more IllegalStateExceptions and leaked window crashes. This was pretty common when the activity was destroyed with the Alert Dialog still there.

Because DialogFragment is a fragment, it integrates into the activity’s lifecycle and ensures that what’s happening in the dialog window remains consistent. It’s a good practice to use DialogFragments to create dialogs in your android application.

Your class must extend DialogFragment with at least onCreateDialog and/or onCreateView implemented.

You can create Dialogs using DialogFragment in two ways:

  • onCreateDialog – Here you can create the AlertDialog using the AlertDialog.Builder class.
  • onCreateView – Here you can create a Dialog using a custom view defined.

In order to create a DialogFragment that shows a Dialog, we need to call the method show() on the DialogFragment instance as:


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");

We can set any tag as the second argument of show().

In order to create a DialogFragment that embeds the dialog in a fragment, we just add the Fragment to the Framelayout as we do it with any Fragment.

Do you know?

You can show the custom views in Fragments as well instead of just Dialogs.

When a DialogFragment class is instantiated. Methods are called in the following order:

  • onCreate
  • onCreateDialog
  • onCreateView
  • onViewCreated
  • onDestroy

Passing Data to and From the DialogFragment

In order to pass the data to the DialogFragment class, we can simply set the data using setArguments on the instance of the class.

In order to return the data from the DialogFragments to the Activity/another fragment, we need to create our custom interface.

In the following section, we’ll be creating an android application that does the following things:

  • Creates a Simple DialogFragment Dialog
  • A DialogFragment embedded in the Activity
  • DialogFragment with a style.
  • DialogFragment that returns data

Project Structure

android dialogfragment project

Code

The code for the activity_main.xml class is given below:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://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>

Each of the Buttons would start a different type of DialogFragment.

The xml layout for the custom view for a DialogFragment is defined in fragment_sample_dialog.xml file as shown below:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://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>

So our Dialog would show a basic Login form.

The code for the MainActivity.java is given below:


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);
    }
}

The above class implements an interface MyDialogFragment.DialogListener which triggers the method onFinishEditDialog whenever the button of the DialogFragment is clicked.
It displays the data entered in the Dialog on the Activity.

The code for the MyDialogFragment.java class is given below:


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);
    }


}

Inside onCreateDialog we create a normal AlertDialog.
dismiss() function closes the Dialog.

The output of the above application in action is given below:

android dialogfragment output

Notice that in the full screen Dialog, the data for the input field was already passed.

That brings an end to this tutorial. You can download the project from the link below:

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages