Dialog

Dialog adalah jendela kecil yang meminta pengguna untuk membuat keputusan atau memasukkan informasi tambahan. Dialog tidak memenuhi layar dan biasanya digunakan untuk peristiwa modal yang mengharuskan pengguna untuk melakukan tindakan sebelum bisa melanjutkan.

Desain Dialog

Untuk informasi tentang cara mendesain dialog, termasuk rekomendasi bahasa, baca panduan desain Dialog.

Class Dialog adalah class dasar untuk dialog, tetapi Anda harus menghindari pembuatan instance Dialog secara langsung. Sebagai gantinya, gunakan salah satu dari subclass berikut:

AlertDialog
Dialog yang bisa menampilkan judul, maksimum tiga tombol, daftar item yang dapat dipilih, atau tata letak kustom.
DatePickerDialog atau TimePickerDialog
Dialog berisi UI yang sudah didefinisikan dan memungkinkan pengguna memilih tanggal atau waktu.

Perhatian: Android menyertakan class dialog lain yang disebut ProgressDialog yang menampilkan dialog dengan status progres. Widget ini tidak digunakan lagi karena mencegah pengguna berinteraksi dengan aplikasi saat progres sedang ditampilkan. Jika Anda perlu menunjukkan progres pemuatan atau tak tentu, Anda harus mengikuti panduan desain untuk Progres & Aktivitas dan menggunakan ProgressBar di tata letak, bukan menggunakan ProgressDialog.

Class ini menetapkan gaya dan struktur untuk dialog Anda, tetapi Anda harus menggunakan DialogFragment sebagai penampung dialog. Class DialogFragment menyediakan semua kontrol yang Anda perlukan untuk membuat dialog dan mengelola tampilannya, bukan memanggil metode pada objek Dialog.

Menggunakan DialogFragment untuk mengelola dialog akan memastikannya menangani peristiwa siklus proses dengan benar seperti ketika pengguna menekan tombol Kembali atau memutar layar. Class DialogFragment juga memungkinkan Anda menggunakan kembali UI dialog sebagai komponen yang bisa disematkan dalam UI yang lebih besar, persis seperti Fragment biasa (misalnya, saat Anda ingin UI dialog muncul berbeda di layar besar dan kecil).

Bagian berikut dalam panduan ini akan menjelaskan cara menggunakan DialogFragment yang dikombinasikan dengan objek AlertDialog. Jika ingin membuat pemilih tanggal atau waktu, Anda harus membaca panduan Pemilih.

Catatan: Karena class DialogFragment mulanya ditambahkan pada Android 3.0 (API level 11), dokumen ini menjelaskan cara menggunakan class DialogFragment yang disediakan bersama Support Library. Dengan menambahkan library ini ke aplikasi, Anda dapat menggunakan DialogFragment dan berbagai API lain pada perangkat yang menjalankan Android 1.6 atau yang lebih baru. Jika versi minimum yang didukung aplikasi Anda adalah API level 11 atau yang lebih baru, Anda dapat menggunakan versi framework DialogFragment, tetapi perhatikan bahwa link dalam dokumen ini adalah untuk support library API. Saat menggunakan support library, pastikan Anda mengimpor class android.support.v4.app.DialogFragment, bukan android.app.DialogFragment.

Membuat Fragmen Dialog

Anda bisa menghasilkan beragam desain dialog, termasuk tata letak kustom dan yang dijelaskan dalam panduan desain Dialog, dengan memperluas DialogFragment dan membuat AlertDialog dalam metode callback onCreateDialog().

Misalnya, berikut AlertDialog dasar yang dikelola dalam DialogFragment:

Kotlin

class StartGameDialogFragment : DialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        return activity?.let {
            // Use the Builder class for convenient dialog construction
            val builder = AlertDialog.Builder(it)
            builder.setMessage(R.string.dialog_start_game)
                    .setPositiveButton(R.string.start,
                            DialogInterface.OnClickListener { dialog, id ->
                                // START THE GAME!
                            })
                    .setNegativeButton(R.string.cancel,
                            DialogInterface.OnClickListener { dialog, id ->
                                // User cancelled the dialog
                            })
            // Create the AlertDialog object and return it
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }
}

Java

public class StartGameDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_start_game)
               .setPositiveButton(R.string.start, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // START THE GAME!
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // User cancelled the dialog
                   }
               });
        // Create the AlertDialog object and return it
        return builder.create();
    }
}

Gambar 1. Dialog dengan satu pesan dan dua tombol tindakan.

Sekarang, bila Anda membuat instance class ini dan memanggil show() pada objek itu, dialog akan muncul seperti yang ditampilkan dalam gambar 1.

Bagian berikutnya menjelaskan selengkapnya penggunaan API AlertDialog.Builder untuk membuat dialog.

Bergantung pada seberapa rumit dialog tersebut, Anda dapat mengimplementasikan berbagai metode callback lain dalam DialogFragment, termasuk semua metode siklus proses fragmen dasar.

Membuat Dialog Peringatan

Class AlertDialog memungkinkan Anda membuat berbagai desain dialog dan sering kali satu-satunya class dialog yang akan Anda perlukan. Seperti yang ditampilkan dalam gambar 2, ada tiga area pada dialog peringatan:

Gambar 2. Tata letak dialog.

  1. Judul

    Area ini opsional dan hanya boleh digunakan bila area isi berisi pesan terperinci, daftar, atau tata letak kustom. Jika Anda perlu menyatakan pesan atau pertanyaan sederhana (seperti dialog dalam gambar 1), Anda tidak memerlukan judul.

  2. Area isi

    Area ini dapat menampilkan pesan, daftar, atau tata letak kustom lainnya.

  3. Tombol tindakan

    Tidak boleh ada lebih dari tiga tombol tindakan dalam dialog.

Class AlertDialog.Builder menyediakan API yang memungkinkan Anda membuat AlertDialog dengan jenis isi ini, termasuk tata letak kustom.

Untuk membuat AlertDialog:

Kotlin

// 1. Instantiate an <code><a href="/reference/android/app/AlertDialog.Builder.html">AlertDialog.Builder</a></code> with its constructor
val builder: AlertDialog.Builder? = activity?.let {
    AlertDialog.Builder(it)
}

// 2. Chain together various setter methods to set the dialog characteristics
builder?.setMessage(R.string.dialog_message)
        .setTitle(R.string.dialog_title)

// 3. Get the <code><a href="/reference/android/app/AlertDialog.html">AlertDialog</a></code> from <code><a href="/reference/android/app/AlertDialog.Builder.html#create()">create()</a></code>
val dialog: AlertDialog? = builder?.create()

Java

// 1. Instantiate an <code><a href="/reference/android/app/AlertDialog.Builder.html">AlertDialog.Builder</a></code> with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage(R.string.dialog_message)
       .setTitle(R.string.dialog_title);

// 3. Get the <code><a href="/reference/android/app/AlertDialog.html">AlertDialog</a></code> from <code><a href="/reference/android/app/AlertDialog.Builder.html#create()">create()</a></code>
AlertDialog dialog = builder.create();

Topik-topik selanjutnya menunjukkan cara menetapkan berbagai atribut dialog menggunakan class AlertDialog.Builder.

Menambahkan tombol

Untuk menambahkan tombol tindakan seperti dalam gambar 2, panggil metode setPositiveButton() dan setNegativeButton():

Kotlin

val alertDialog: AlertDialog? = activity?.let {
    val builder = AlertDialog.Builder(it)
    builder.apply {
        setPositiveButton(R.string.ok,
                DialogInterface.OnClickListener { dialog, id ->
                    // User clicked OK button
                })
        setNegativeButton(R.string.cancel,
                DialogInterface.OnClickListener { dialog, id ->
                    // User cancelled the dialog
                })
    }
    // Set other dialog properties
    ...

    // Create the AlertDialog
    builder.create()
}

Java

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User clicked OK button
           }
       });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User cancelled the dialog
           }
       });
// Set other dialog properties
...

// Create the AlertDialog
AlertDialog dialog = builder.create();

Metode set...Button() mengharuskan judul tombol (disediakan oleh resource string) dan DialogInterface.OnClickListener yang menetapkan tindakan untuk dilakukan bila pengguna menekan tombol.

Ada tiga tombol tindakan yang dapat ditambahkan:

Positif
Anda harus menggunakan ini untuk menerima dan melanjutkan tindakan (tindakan "Oke").
Negatif
Anda harus menggunakan tipe ini untuk membatalkan tindakan.
Netral
Anda harus menggunakan tipe ini bila pengguna mungkin tidak ingin melanjutkan tindakan, tetapi tidak ingin membatalkannya. Tipe ini muncul antara tombol positif dan tombol negatif. Misalnya, tindakan dapat berupa "Ingatkan saya nanti".

Anda hanya bisa menambahkan satu dari setiap tipe tombol ke AlertDialog. Artinya, Anda tidak dapat memiliki lebih dari satu tombol "positif".

Gambar 3. Dialog dengan satu judul dan daftar.

Menambahkan daftar

Ada tiga jenis daftar yang tersedia pada API AlertDialog:

  • Daftar pilihan tunggal biasa
  • Daftar pilihan tunggal persisten (tombol pilihan)
  • Daftar pilihan ganda persisten (kotak centang)

Untuk membuat daftar pilihan tunggal seperti dalam gambar 3, gunakan metode setItems():

Kotlin

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return activity?.let {
        val builder = AlertDialog.Builder(it)
        builder.setTitle(R.string.pick_color)
                .setItems(R.array.colors_array,
                        DialogInterface.OnClickListener { dialog, which ->
                            // The 'which' argument contains the index position
                            // of the selected item
                        })
        builder.create()
    } ?: throw IllegalStateException("Activity cannot be null")
}

Java

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle(R.string.pick_color)
           .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int which) {
               // The 'which' argument contains the index position
               // of the selected item
           }
    });
    return builder.create();
}

Karena daftar muncul dalam area isi dialog, dialog tidak bisa menampilkan pesan dan daftar sekaligus. Anda juga harus menetapkan judul untuk dialog dengan setTitle(). Untuk menetapkan item untuk daftar, panggil setItems(), dengan meneruskan array. Atau, Anda dapat menetapkan daftar menggunakan setAdapter(). Hal ini memungkinkan Anda mendukung daftar dengan data dinamis (seperti dari database) menggunakan ListAdapter.

Jika Anda memilih untuk mendukung daftar dengan ListAdapter, selalu gunakan Loader agar isi dimuat secara asinkron. Hal ini dijelaskan lebih jauh dalam panduan Membangun Tata Letak dengan Adaptor dan panduan Loader.

Catatan: Secara default, menyentuh item daftar akan menutup dialog, kecuali jika Anda menggunakan salah satu daftar pilihan persisten berikut.

Menambahkan daftar pilihan ganda atau pilihan tunggal persisten

Untuk menambahkan daftar item pilihan ganda (kotak centang) atau item pilihan tunggal (tombol pilihan), masing-masing gunakan metode setMultiChoiceItems() atau setSingleChoiceItems().

Gambar 4. Daftar item pilihan ganda.

Misalnya, berikut cara membuat daftar pilihan ganda seperti yang ditampilkan dalam gambar 4 yang menyimpan item terpilih dalam ArrayList:

Kotlin

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return activity?.let {
        val selectedItems = ArrayList<Int>() // Where we track the selected items
        val builder = AlertDialog.Builder(it)
        // Set the dialog title
        builder.setTitle(R.string.pick_toppings)
                // Specify the list array, the items to be selected by default (null for none),
                // and the listener through which to receive callbacks when items are selected
                .setMultiChoiceItems(R.array.toppings, null,
                        DialogInterface.OnMultiChoiceClickListener { dialog, which, isChecked ->
                            if (isChecked) {
                                // If the user checked the item, add it to the selected items
                                selectedItems.add(which)
                            } else if (selectedItems.contains(which)) {
                                // Else, if the item is already in the array, remove it
                                selectedItems.remove(which)
                            }
                        })
                // Set the action buttons
                .setPositiveButton(R.string.ok,
                        DialogInterface.OnClickListener { dialog, id ->
                            // User clicked OK, so save the selectedItems results somewhere
                            // or return them to the component that opened the dialog
                            ...
                        })
                .setNegativeButton(R.string.cancel,
                        DialogInterface.OnClickListener { dialog, id ->
                            ...
                        })

        builder.create()
    } ?: throw IllegalStateException("Activity cannot be null")
}

Java

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    selectedItems = new ArrayList();  // Where we track the selected items
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Set the dialog title
    builder.setTitle(R.string.pick_toppings)
    // Specify the list array, the items to be selected by default (null for none),
    // and the listener through which to receive callbacks when items are selected
           .setMultiChoiceItems(R.array.toppings, null,
                      new DialogInterface.OnMultiChoiceClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which,
                       boolean isChecked) {
                   if (isChecked) {
                       // If the user checked the item, add it to the selected items
                       selectedItems.add(which);
                   } else if (selectedItems.contains(which)) {
                       // Else, if the item is already in the array, remove it
                       selectedItems.remove(which);
                   }
               }
           })
    // Set the action buttons
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // User clicked OK, so save the selectedItems results somewhere
                   // or return them to the component that opened the dialog
                   ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   ...
               }
           });

    return builder.create();
}

Meskipun daftar biasa dan daftar dengan tombol pilihan menyediakan tindakan "pilihan tunggal", Anda harus menggunakan setSingleChoiceItems() jika ingin mempertahankan pilihan pengguna. Dengan begitu, jika nanti membuka dialog lagi untuk menunjukkan pilihan pengguna saat ini, Anda perlu membuat daftar dengan tombol pilihan.

Membuat Tata Letak Kustom

Gambar 5. Tata letak dialog kustom.

Jika Anda menginginkan tata letak kustom dalam dialog, buat tata letak dan tambahkan ke AlertDialog dengan memanggil setView() pada objek AlertDialog.Builder.

Secara default, tata letak kustom akan mengisi jendela dialog, tetapi Anda tetap dapat menggunakan metode AlertDialog.Builder untuk menambahkan tombol dan judul.

Misalnya, berikut adalah file tata letak untuk dialog dalam Gambar 5:

res/layout/dialog_signin.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <ImageView
        android:src="@drawable/header_logo"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:scaleType="center"
        android:background="#FFFFBB33"
        android:contentDescription="@string/app_name" />
    <EditText
        android:id="@+id/username"
        android:inputType="textEmailAddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="4dp"
        android:hint="@string/username" />
    <EditText
        android:id="@+id/password"
        android:inputType="textPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="16dp"
        android:fontFamily="sans-serif"
        android:hint="@string/password"/>
</LinearLayout>

Tips: Secara default, saat Anda menyetel elemen EditText untuk menggunakan jenis input "textPassword", jenis font ditetapkan ke monospace, jadi Anda harus mengubah jenis fontnya menjadi "sans-serif", sehingga kedua kolom teks menggunakan gaya font yang cocok.

Untuk meng-inflate tata letak dalam DialogFragment, ambil LayoutInflater dengan getLayoutInflater() dan panggil inflate(), dengan parameter pertama adalah ID resource tata letak dan parameter kedua adalah tampilan induk tata letak. Selanjutnya Anda bisa memanggil setView() untuk menempatkan tata letak dalam dialog.

Kotlin

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return activity?.let {
        val builder = AlertDialog.Builder(it)
        // Get the layout inflater
        val inflater = requireActivity().layoutInflater;

        // Inflate and set the layout for the dialog
        // Pass null as the parent view because its going in the dialog layout
        builder.setView(inflater.inflate(R.layout.dialog_signin, null))
                // Add action buttons
                .setPositiveButton(R.string.signin,
                        DialogInterface.OnClickListener { dialog, id ->
                            // sign in the user ...
                        })
                .setNegativeButton(R.string.cancel,
                        DialogInterface.OnClickListener { dialog, id ->
                            getDialog().cancel()
                        })
        builder.create()
    } ?: throw IllegalStateException("Activity cannot be null")
}

Java

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Get the layout inflater
    LayoutInflater inflater = requireActivity().getLayoutInflater();

    // Inflate and set the layout for the dialog
    // Pass null as the parent view because its going in the dialog layout
    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
    // Add action buttons
           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // sign in the user ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   LoginDialogFragment.this.getDialog().cancel();
               }
           });
    return builder.create();
}

Tips: Jika menginginkan dialog kustom, Anda dapat menampilkan Activity sebagai dialog, bukan menggunakan API Dialog. Cukup buat satu aktivitas dan setel temanya ke Theme.Holo.Dialog di elemen manifes <activity>:

<activity android:theme="@android:style/Theme.Holo.Dialog" >

Selesai. Aktivitas sekarang ditampilkan dalam jendela dialog, bukan layar penuh.

Meneruskan Peristiwa Kembali ke Host Dialog

Bila pengguna menyentuh salah satu tombol tindakan dialog atau memilih satu item dari daftarnya, DialogFragment Anda dapat melakukan sendiri tindakan yang diperlukan, tetapi sering kali Anda perlu mengirim peristiwa tersebut ke aktivitas atau fragmen yang membuka dialog. Caranya, tentukan antarmuka dengan metode untuk setiap jenis peristiwa klik. Lalu, implementasikan antarmuka tersebut dalam komponen host yang akan menerima peristiwa tindakan dari dialog.

Misalnya, berikut adalah DialogFragment yang menetapkan antarmuka yang akan digunakan untuk mengirim kembali suatu peristiwa ke aktivitas host:

Kotlin

class NoticeDialogFragment : DialogFragment() {
    // Use this instance of the interface to deliver action events
    internal lateinit var listener: NoticeDialogListener

    /* The activity that creates an instance of this dialog fragment must
     * implement this interface in order to receive event callbacks.
     * Each method passes the DialogFragment in case the host needs to query it. */
    interface NoticeDialogListener {
        fun onDialogPositiveClick(dialog: DialogFragment)
        fun onDialogNegativeClick(dialog: DialogFragment)
    }

    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Verify that the host activity implements the callback interface
        try {
            // Instantiate the NoticeDialogListener so we can send events to the host
            listener = context as NoticeDialogListener
        } catch (e: ClassCastException) {
            // The activity doesn't implement the interface, throw exception
            throw ClassCastException((context.toString() +
                    " must implement NoticeDialogListener"))
        }
    }
}

Java

public class NoticeDialogFragment extends DialogFragment {

    /* The activity that creates an instance of this dialog fragment must
     * implement this interface in order to receive event callbacks.
     * Each method passes the DialogFragment in case the host needs to query it. */
    public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
    }

    // Use this instance of the interface to deliver action events
    NoticeDialogListener listener;

    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // Verify that the host activity implements the callback interface
        try {
            // Instantiate the NoticeDialogListener so we can send events to the host
            listener = (NoticeDialogListener) context;
        } catch (ClassCastException e) {
            // The activity doesn't implement the interface, throw exception
            throw new ClassCastException(activity.toString()
                    + " must implement NoticeDialogListener");
        }
    }
    ...
}

Aktivitas yang menghosting dialog akan membuat instance dialog dengan konstruktor fragmen dialog dan menerima peristiwa dialog melalui implementasi antarmuka NoticeDialogListener:

Kotlin

class MainActivity : FragmentActivity(),
        NoticeDialogFragment.NoticeDialogListener {

    fun showNoticeDialog() {
        // Create an instance of the dialog fragment and show it
        val dialog = NoticeDialogFragment()
        dialog.show(supportFragmentManager, "NoticeDialogFragment")
    }

    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following methods
    // defined by the NoticeDialogFragment.NoticeDialogListener interface
    override fun onDialogPositiveClick(dialog: DialogFragment) {
        // User touched the dialog's positive button
    }

    override fun onDialogNegativeClick(dialog: DialogFragment) {
        // User touched the dialog's negative button
    }
}

Java

public class MainActivity extends FragmentActivity
                          implements NoticeDialogFragment.NoticeDialogListener{
    ...

    public void showNoticeDialog() {
        // Create an instance of the dialog fragment and show it
        DialogFragment dialog = new NoticeDialogFragment();
        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
    }

    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following methods
    // defined by the NoticeDialogFragment.NoticeDialogListener interface
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        // User touched the dialog's positive button
        ...
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        // User touched the dialog's negative button
        ...
    }
}

Karena aktivitas host mengimplementasikan NoticeDialogListener, yang diberlakukan oleh metode callback onAttach() di atas, fragmen dialog dapat menggunakan metode callback antarmuka untuk mengirimkan peristiwa klik ke aktivitas:

Kotlin

    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        return activity?.let {
            // Build the dialog and set up the button click handlers
            val builder = AlertDialog.Builder(it)

            builder.setMessage(R.string.dialog_start_game)
                    .setPositiveButton(R.string.start,
                            DialogInterface.OnClickListener { dialog, id ->
                                // Send the positive button event back to the host activity
                                listener.onDialogPositiveClick(this)
                            })
                    .setNegativeButton(R.string.cancel,
                            DialogInterface.OnClickListener { dialog, id ->
                                // Send the negative button event back to the host activity
                                listener.onDialogNegativeClick(this)
                            })

            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }

Java

public class NoticeDialogFragment extends DialogFragment {
    ...

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Build the dialog and set up the button click handlers
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_start_game)
               .setPositiveButton(R.string.start, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the positive button event back to the host activity
                       listener.onDialogPositiveClick(NoticeDialogFragment.this);
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the negative button event back to the host activity
                       listener.onDialogNegativeClick(NoticeDialogFragment.this);
                   }
               });
        return builder.create();
    }
}

Menampilkan Dialog

Bila Anda ingin menampilkan dialog, buat instance DialogFragment dan panggil show(), dengan meneruskan FragmentManager dan nama tag untuk fragmen dialognya.

Anda bisa mendapatkan FragmentManager dengan memanggil getSupportFragmentManager() dari FragmentActivity atau getFragmentManager() dari Fragment. Contoh:

Kotlin

fun confirmStartGame() {
    val newFragment = StartGameDialogFragment()
    newFragment.show(supportFragmentManager, "game")
}

Java

public void confirmStartGame() {
    DialogFragment newFragment = new StartGameDialogFragment();
    newFragment.show(getSupportFragmentManager(), "game");
}

Argumen kedua, "game", adalah nama tag unik yang digunakan sistem untuk menyimpan dan memulihkan status fragmen bila diperlukan. Tag ini juga memungkinkan Anda mendapatkan tuas ke fragmen dengan memanggil findFragmentByTag().

Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tersemat

Anda mungkin memiliki desain UI yang Anda ingin bagian dari UI tersebut muncul sebagai dialog dalam sejumlah situasi, dan sebagai layar penuh atau fragmen tersemat dalam situasi lain (mungkin bergantung pada apakah perangkat memiliki layar besar atau layar kecil). Class DialogFragment menawarkan fleksibilitas ini karena masih bisa berperilaku sebagai Fragment yang dapat disematkan.

Akan tetapi, dalam hal ini Anda tidak bisa menggunakan AlertDialog.Builder atau objek Dialog lain untuk membangun dialog. Jika ingin DialogFragment bisa disematkan, Anda harus menetapkan UI dialog dalam tata letak, lalu memuat tata letak tersebut dalam callback onCreateView().

Berikut adalah contoh DialogFragment yang bisa muncul sebagai dialog maupun fragmen yang bisa disematkan (menggunakan tata letak purchase_items.xml):

Kotlin

class CustomDialogFragment : DialogFragment() {

    /** The system calls this to get the DialogFragment's layout, regardless
    of whether it's being displayed as a dialog or an embedded fragment. */
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        // Inflate the layout to use as dialog or embedded fragment
        return inflater.inflate(R.layout.purchase_items, container, false)
    }

    /** The system calls this only when creating the layout in a dialog. */
    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        // The only reason you might override this method when using onCreateView() is
        // to modify any dialog characteristics. For example, the dialog includes a
        // title by default, but your custom layout might not need it. So here you can
        // remove the dialog title, but you must call the superclass to get the Dialog.
        val dialog = super.onCreateDialog(savedInstanceState)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        return dialog
    }
}

Java

public class CustomDialogFragment extends DialogFragment {
    /** The system calls this to get the DialogFragment's layout, regardless
        of whether it's being displayed as a dialog or an embedded fragment. */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout to use as dialog or embedded fragment
        return inflater.inflate(R.layout.purchase_items, container, false);
    }

    /** The system calls this only when creating the layout in a dialog. */
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // The only reason you might override this method when using onCreateView() is
        // to modify any dialog characteristics. For example, the dialog includes a
        // title by default, but your custom layout might not need it. So here you can
        // remove the dialog title, but you must call the superclass to get the Dialog.
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;
    }
}

Dan berikut adalah kode tertentu yang memutuskan apakah akan menampilkan fragmen sebagai dialog atau UI layar penuh, berdasarkan ukuran layar:

Kotlin

fun showDialog() {
    val fragmentManager = supportFragmentManager
    val newFragment = CustomDialogFragment()
    if (isLargeLayout) {
        // The device is using a large layout, so show the fragment as a dialog
        newFragment.show(fragmentManager, "dialog")
    } else {
        // The device is smaller, so show the fragment fullscreen
        val transaction = fragmentManager.beginTransaction()
        // For a little polish, specify a transition animation
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity
        transaction
                .add(android.R.id.content, newFragment)
                .addToBackStack(null)
                .commit()
    }
}

Java

public void showDialog() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    CustomDialogFragment newFragment = new CustomDialogFragment();

    if (isLargeLayout) {
        // The device is using a large layout, so show the fragment as a dialog
        newFragment.show(fragmentManager, "dialog");
    } else {
        // The device is smaller, so show the fragment fullscreen
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        // For a little polish, specify a transition animation
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity
        transaction.add(android.R.id.content, newFragment)
                   .addToBackStack(null).commit();
    }
}

Untuk informasi selengkapnya tentang cara melakukan transaksi fragmen, lihat panduan Fragmen.

Dalam contoh ini, nilai (logika) Boolean mIsLargeLayout menentukan apakah perangkat saat ini harus menggunakan desain tata letak besar aplikasi (dan dengan demikian menampilkan fragmen ini sebagai dialog, bukan layar penuh). Cara terbaik untuk menyetel jenis (logika) Boolean ini adalah mendeklarasikan nilai resource boolean dengan nilai resource alternatif untuk berbagai ukuran layar. Misalnya, berikut ini adalah dua versi resource boolean untuk berbagai ukuran layar:

res/values/bools.xml

<!-- Default boolean values -->
<resources>
    <bool name="large_layout">false</bool>
</resources>

res/values-large/bools.xml

<!-- Large screen boolean values -->
<resources>
    <bool name="large_layout">true</bool>
</resources>

Selanjutnya, Anda dapat melakukan inisialiasi nilai mIsLargeLayout selama metode onCreate() aktivitas:

Kotlin

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

    isLargeLayout = resources.getBoolean(R.bool.large_layout)
}

Java

boolean isLargeLayout;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    isLargeLayout = getResources().getBoolean(R.bool.large_layout);
}

Menampilkan aktivitas sebagai dialog di layar besar

Sebagai ganti menampilkan dialog berupa UI layar penuh di layar kecil, Anda bisa memperoleh hasil yang sama dengan menampilkan Activity sebagai dialog di layar besar. Pendekatan yang Anda pilih bergantung pada desain aplikasi, tetapi menampilkan aktivitas sebagai dialog sering kali berguna jika aplikasi sudah didesain untuk layar kecil dan Anda ingin meningkatkan pengalaman pada tablet dengan menampilkan aktivitas berjangka pendek sebagai dialog.

Untuk hanya menampilkan aktivitas sebagai dialog di layar besar, terapkan tema Theme.Holo.DialogWhenLarge pada elemen manifes <activity>:

<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >

Untuk informasi selengkapnya tentang menata gaya aktivitas Anda dengan tema, lihat panduan Gaya dan Tema.

Menutup Dialog

Jika pengguna menyentuh salah satu tombol tindakan yang dibuat dengan AlertDialog.Builder, sistem akan menutup dialog untuk Anda.

Sistem juga menutup dialog bila pengguna menyentuh sebuah item dalam daftar dialog, kecuali jika daftar itu menggunakan tombol pilihan atau kotak centang. Jika tidak, Anda bisa menutup dialog secara manual dengan memanggil dismiss() pada DialogFragment.

Jika Anda perlu melakukan tindakan tertentu saat dialog menghilang, Anda bisa mengimplementasikan metode onDismiss() dalam DialogFragment.

Anda juga bisa membatalkan dialog. Ini merupakan peristiwa khusus yang menunjukkan bahwa pengguna secara eksplisit meninggalkan dialog tanpa menyelesaikan tugas. Hal ini terjadi jika pengguna menekan tombol Kembali, menyentuh layar di luar area dialog, atau jika Anda secara eksplisit memanggil cancel() di Dialog (misalnya, sebagai respons terhadap tombol "Batal" di dialog).

Seperti yang ditampilkan dalam contoh di atas, Anda bisa merespons peristiwa batal dengan mengimplementasikan onCancel() dalam class DialogFragment.

Catatan: Sistem memanggil onDismiss() pada setiap peristiwa yang memanggil callback onCancel(). Namun, jika Anda memanggil Dialog.dismiss() atau DialogFragment.dismiss(), sistem akan memanggil onDismiss(), tetapi bukan onCancel(). Jadi, Anda biasanya harus memanggil dismiss() jika pengguna menekan tombol positif dalam dialog untuk membuang dialog dari tampilan.