How to Create a Custom Dialog (Android)

April 21, 2019

A dialog is a fragment shown which cover 90% of the screen with remaining 10% is black opacity background.

Android Dialog

There are 2 types of custom dialog

  • Dialog with Ok/Cancel button at the buttom, which utilize AlertDialog
  • Dialog with just a view (no button)

NOTE: You can show an AlertDialog without implementing a custom dialog class

Dialog by default comes with title (or space allocated for title). You can opt to hide the dialog title.

Solution 1: Custom AlertDialog with Ok/Cancel button

class CustomDialog : DialogFragment() {
    companion object {
        private const val FRAGMENT_TAG = "custom_dialog"

        fun newInstance() = CustomDialog()

        fun show(fragmentManager: FragmentManager): CustomDialog {
            val dialog = newInstance()
            // dialog.isCancelable = false
            dialog.show(fragmentManager, FRAGMENT_TAG)
            return dialog
        }
    }

    private lateinit var customView: View

    // refer to https://code.luasoftware.com/tutorials/android/android-alertdialog-in-dialogfragment-fragment-does-not-have-a-view/
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // return super.onCreateView(inflater, container, savedInstanceState)
        return customView
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        // return super.onCreateDialog(savedInstanceState)

        val view = activity!!.layoutInflater.inflate(R.layout.customdialog, null)
        customView = view

        val builder = AlertDialog.Builder(context!!)
            .setTitle("Custom Dialog")
            .setView(view)
            .setPositiveButton(android.R.string.ok) { _, _ ->
                // do something
            }
            .setNegativeButton(android.R.string.cancel) { _, _ ->
                // do something
            }

        val dialog = builder.create()

        // optional
        dialog.setOnShowListener {
            // do something
        }

        return dialog
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        textView.text = "Hello"
    }
}

Layout

<RelativeLayout 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"
    android:padding="?dialogPreferredPadding"
    >


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />

    </LinearLayout>
</RelativeLayout>

Solution 2: Custom Dialog with View only

class CustomDialog: DialogFragment() {
    companion object {
        private const val FRAGMENT_TAG = "custom_dialog"

        fun newInstance() = CustomDialog()

        fun show(fragmentManager: FragmentManager): CustomDialog {
            val dialog = newInstance()
            // dialog.isCancelable = false
            dialog.show(fragmentManager, FRAGMENT_TAG)
            return dialog
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // return super.onCreateView(inflater, container, savedInstanceState)

        dialog?.setTitle("Custom Dialog")
        return activity!!.layoutInflater.inflate(R.layout.customdialog, container)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        textView.text = "Hello"
    }
}

NOTE: Apply the layout of Solution 1

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.