Android DialogFragment Example

This article is about Android DialogFragment and how to work with it with the help of simple examples.

Android DialogFragment

A Dialog Fragment is a fragment that is used to make Dialogs that floats on Activity.

 

Android DialogFragment

A DialogFragment is a fragment that is used to make Dialogs that floats on Activity.

DialogFragment extends the Fragment class. All the information regarding the Dialog or the data associated with the Dialog will be stored or managed in the Fragment only. 

Since DialogFragment is associated with Fragment, so it has its own LifeCycle and now the Activity need not manage the lifecycle of Dialogs. Due to this reason, DialogFragments are recommended to be used while implementing Alert Dialog or any other type of Dialog in Android.

DialogFragment lifecycle

DialogFragment follows the standard fragment lifecycle. In addition, DialogFragment has a few additional lifecycle callbacks. The most common ones are as follows:

  • onCreateDialog() – Override this callback to provide a Dialog for the fragment to manage and display.
  • onDismiss() – Override this callback if you need to perform any custom logic when your Dialog is dismissed, such as releasing resources, unsubscribing from observable resources, and so on.
  • onCancel() – Override this callback if you need to perform any custom logic when your Dialog is cancelled.

DialogFragment also contains methods to dismiss or set the cancellability of your DialogFragment:

Steps of creating custom Dialog

To create a dialog fragment of our own follows the below steps:

  • Create a Kotlin/Java file for your Dialog Fragment. For example, MyDialog.kt and this class will extend the DialogFragment. Here in this class, override all the methods related to dialog.
  • Create the layout file of the dialog. 
  • Call your custom dialog from your Activity.

Creating new project

1. Create a new project by going to File  New Android Project, select Empty Activity, provide app name, select language to kotlin and then finally click on finish.

2. Open app-level build.gradle file and add the dependency of Livedata and ViewModel.

dependencies {
//viewmodel and livedata dependency
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
}

Creating Custom Dialog Example

1 . Create a layout file named fragment_custom_dialog.xml which represents the UI of the custom dialog. It consists of a title, a subtitle, and two buttons (for positive and negative responses).

fragment_custom_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp">

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvSubTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:textColor="@android:color/black"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvTitle" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnPositive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="OK"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvSubTitle" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnNegative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="CANCEL"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btnPositive"
app:layout_constraintTop_toBottomOf="@+id/tvSubTitle" />

</androidx.constraintlayout.widget.ConstraintLayout>

2. Create a CustomDialogFragment class (subclass of DialogFragment) under the root directory, right-click > New > Kotlin File/Class.

CustomDialogFragment.kt

package com.c1ctech.dialogfragmentdemo

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import kotlinx.android.synthetic.main.fragment_custom_dialog.view.*

class CustomDialogFragment : DialogFragment() {

companion object {

const val TAG = "CustomDialogFragment"

private const val KEY_TITLE = "KEY_TITLE"
private const val KEY_SUBTITLE = "KEY_SUBTITLE"

//take the title and subtitle form the Activity
fun newInstance(title: String, subTitle: String): CustomDialogFragment {
val args = Bundle()
args.putString(KEY_TITLE, title)
args.putString(KEY_SUBTITLE, subTitle)
val fragment = CustomDialogFragment()
fragment.arguments = args
return fragment
}

}

//creating the Dialog Fragment.
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_custom_dialog, container, false)
}

//tasks that need to be done after the creation of Dialog
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupView(view)
setupClickListeners(view)
}

override fun onStart() {
super.onStart()
dialog?.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
}

//setting the text in CustomDialog
private fun setupView(view: View) {

view.tvTitle.text = arguments?.getString(KEY_TITLE)
view.tvSubTitle.text = arguments?.getString(KEY_SUBTITLE)
}

//setting all the click listeners of the CustomDialog
private fun setupClickListeners(view: View) {

// On clicking the positive/negative button,
// the dialog will be closed with the help of dismiss()
view.btnPositive.setOnClickListener {
dismiss()
}
view.btnNegative.setOnClickListener {
dismiss()
}
}
}

3. Now, from the MainActivity, we will open the custom Dialog on button click. 

MainActivity.kt

btnCustomDialog.setOnClickListener {
CustomDialogFragment.newInstance(
getString(R.string.custom_dialog_title),
getString(R.string.custom_dialog_subTitle)
).show(supportFragmentManager, CustomDialogFragment.TAG)
}

Run the app. On click of Custom Dialog Fragment button the custom dialog will appear like this:

 

Creating an Alert Dialog Example

If you want to use the AlertDialog provided by Android instead of your own custom dialog, then you have to override the onCreateDialog method and create your AlertDialog there. 

Note: No need to override onCreateView() or onViewCreated() when using a DialogFragment with a Dialog(provided by Android).

1. Create the AlertDialogFragment class (under the root directory, right-click > New > Kotlin File/Class)

AlertDialogFragment.kt

package com.c1ctech.dialogfragmentdemo

import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment

class AlertDialogFragment : DialogFragment() {

companion object {
const val TAG = "AlertDialogFragment"

//create fragment instance
fun newInstance(): AlertDialogFragment {
val fragment = AlertDialogFragment()
return fragment
}
}

//creating the AlertDialog
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = activity?.let { AlertDialog.Builder(it) }
builder?.setTitle(R.string.alert_dialog_title)
builder?.setMessage(R.string.alert_dialog_subTitle)
builder?.setPositiveButton("Yes", object : DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int) {
dismiss()
}
})
builder?.setNegativeButton("No", object : DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int) {
dismiss()
}
})
return builder?.create()!!
}
}

Run the app. On click of  Alert Dialog Fragment button the Alertdialog will appear on the screen like this:

 

Creating Dialog containing data shared with Activity/Fragment Example

In this example, we have one EditText in the DialogFragment and a button. On clicking the button, the text in the EditText will be displayed on the MainActivity.

1. The layout file fragment_dialog_with_data.xml represents the UI of the dialog. It consists of one TextView, one EditText, and a Button.

fragment_dialog_with_data.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp">

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Enter your details"
android:textAlignment="center"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/etName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:hint="Enter your name"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnSubmit"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:text="Submit"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etName" />

</androidx.constraintlayout.widget.ConstraintLayout>

NOTE: Don’t forget to add the dependency of LiveData and ViewModel.

2. In the activity_main.xml file, we need to add one button and one text view for displaying the name. 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnAlertDialog"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="12dp"
android:text="@string/btn_AlertDialog"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnCustomDialog"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="12dp"
android:text="@string/btn_Custom_Dialog"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="@+id/btnAlertDialog"
app:layout_constraintStart_toStartOf="@+id/btnAlertDialog"
app:layout_constraintTop_toBottomOf="@+id/btnAlertDialog" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnDataDialog"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="12dp"
android:text="@string/btn_Dialog_with_data"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="@+id/btnCustomDialog"
app:layout_constraintStart_toStartOf="@+id/btnCustomDialog"
app:layout_constraintTop_toBottomOf="@+id/btnCustomDialog" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/holo_red_dark"
app:layout_constraintEnd_toEndOf="@+id/btnDataDialog"
app:layout_constraintStart_toStartOf="@+id/btnDataDialog"
app:layout_constraintTop_toBottomOf="@+id/btnDataDialog" />

</androidx.constraintlayout.widget.ConstraintLayout>

3. Create a class named SharedViewModel and add the below code.

SharedViewModel.kt

class SharedViewModel : ViewModel() {
val name = MutableLiveData<String>()

fun sendName(text: String) {
name.value = text
}
}

4. Create a class named DialogWithDataFragment and add the below code.

DialogWithDataFragment.kt

package com.c1ctech.dialogfragmentdemo

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProvider
import kotlinx.android.synthetic.main.fragment_dialog_with_data.view.*

class DialogWithDataFragment : DialogFragment() {

companion object {
const val TAG = "DialogWithDataFragment"
}

private lateinit var viewModel: SharedViewModel

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_dialog_with_data, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
setupClickListeners(view)
}

override fun onStart() {
super.onStart()
dialog?.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
}

private fun setupClickListeners(view: View) {
view.btnSubmit.setOnClickListener {
viewModel.sendName(view.etName.text.toString())
dismiss()
}
}
}

Here, on click of the submit button, the sendName() method of the SharedViewModel is called.

Now, the name needs to be observed in the MainActivity and also we need to implement the click listener of the button to open the DialogWithDataFragment

5. Given below is the complete code of MainActivity.

MainActivity.kt

package com.c1ctech.dialogfragmentdemo

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

private lateinit var sharedViewModel: SharedViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
sharedViewModel.name.observe(this, Observer {
tvName.text = it
})

btnAlertDialog.setOnClickListener {
AlertDialogFragment.newInstance().show(supportFragmentManager, AlertDialogFragment.TAG)
}

btnCustomDialog.setOnClickListener {
CustomDialogFragment.newInstance(
getString(R.string.custom_dialog_title),
getString(R.string.custom_dialog_subTitle)
).show(supportFragmentManager, CustomDialogFragment.TAG)
}

btnDataDialog.setOnClickListener {
DialogWithDataFragment().show(supportFragmentManager, DialogWithDataFragment.TAG)
}
}
}

Run the app and click on Dialog with data Fragment button. In the dialog, enter some data in the EditText, click on submit and see the text in MainActivity.

     

Leave a Reply