对话框

尝试 Compose 方法
Jetpack Compose 是 Android 推荐的 UI 工具包。了解如何在 Compose 中添加组件。

对话框 是一个小的窗口,提示用户做出决定或输入更多信息。对话框不会填充整个屏幕,通常用于需要用户采取操作才能继续的模态事件。

An image showing a basic dialog
图 1. 一个基本对话框。

The Dialog 类是对话框的基类,但不要直接实例化 Dialog。 相反,使用以下子类之一

AlertDialog
一个可以显示标题、最多三个按钮、一个可选择项列表或自定义布局的对话框。
DatePickerDialogTimePickerDialog
具有预定义 UI 的对话框,允许用户选择日期或时间。

这些类定义了对话框的样式和结构。您还需要一个 DialogFragment 作为对话框的容器。The DialogFragment 类提供创建对话框并管理其外观所需的所有控件,而不是调用 Dialog 对象上的方法。

使用 DialogFragment 来管理对话框可以使其正确处理生命周期事件,例如用户点击后退按钮或旋转屏幕时。The DialogFragment 类还允许您将对话框的 UI 作为可嵌入组件嵌入到更大的 UI 中(就像传统的 Fragment 一样),例如当您希望对话框 UI 在大屏幕和小屏幕上显示不同时。

本文档中的以下部分介绍了如何在 DialogFragmentAlertDialog 对象结合使用。如果您想创建日期或时间选择器,请阅读 向您的应用添加选择器

创建对话框片段

您可以通过扩展 DialogFragment 并在 onCreateDialog() 回调方法中创建 AlertDialog 来实现各种对话框设计(包括自定义布局和 Material Design 对话框 中描述的布局)。

例如,以下是一个由 DialogFragment 管理的基本 AlertDialog

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("Start game")
                .setPositiveButton("Start") { dialog, id ->
                    // START THE GAME!
                }
                .setNegativeButton("Cancel") { dialog, id ->
                    // User cancelled the dialog.
                }
            // Create the AlertDialog object and return it.
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }
}

class OldXmlActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_old_xml)

        StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG")
    }
}

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 cancels the dialog.
                   }
               });
        // Create the AlertDialog object and return it.
        return builder.create();
    }
}
// ...

StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG");

当您创建此类的实例并调用该对象上的 show() 时,对话框将显示在以下图中。

An image showing a basic dialog with two action buttons
图 2. 一个带有消息和两个操作按钮的对话框。

下一部分将详细介绍如何使用 AlertDialog.Builder API 创建对话框。

根据对话框的复杂程度,您可以在 DialogFragment 中实现各种其他回调方法,包括所有基本 片段生命周期方法

构建警报对话框

The AlertDialog 类允许您构建各种对话框设计,通常是您唯一需要的对话框类。如下图所示,警报对话框有三个区域

  • 标题: 这是可选的,仅在内容区域被详细消息、列表或自定义布局占用时使用。 如果您需要陈述简单消息或问题,则不需要标题。
  • 内容区域: 这里可以显示消息、列表或其他自定义布局。
  • 操作按钮: 对话框中最多可以有三个操作按钮。

The AlertDialog.Builder 类提供了 API,允许您使用这些类型的 content 创建 AlertDialog,包括自定义布局。

要构建 AlertDialog,请执行以下操作

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setMessage("I am the message")
    .setTitle("I am the title")

val dialog: AlertDialog = builder.create()
dialog.show()

Java

// 1. Instantiate an AlertDialog.Builder 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 AlertDialog.
AlertDialog dialog = builder.create();

前面的代码片段生成了以下对话框

An image showing a dialog with title, content area and two action buttons.
图 3. 基本警报对话框的布局。

添加按钮

要添加类似于图 2 中的 action 按钮,请调用 setPositiveButton()setNegativeButton() 方法

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setMessage("I am the message")
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

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 taps OK button.
           }
       });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User cancels the dialog.
           }
       });
// Set other dialog properties.
...

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

The set...Button() 方法需要一个按钮标题(由 字符串资源 提供)和一个 DialogInterface.OnClickListener,用于定义用户点击按钮时要执行的操作。

您可以添加三种 action 按钮

  • 肯定: 用于接受并继续操作(“确定”操作)。
  • 否定: 用于取消操作。
  • 中立: 当用户可能不想继续操作但也不想取消时使用。 它显示在肯定按钮和否定按钮之间。 例如,该操作可能是“稍后提醒我”。

您只能向 AlertDialog 添加每种按钮类型的一个。 例如,您不能有多个“肯定”按钮。

前面的代码片段为您提供了以下警报对话框

An image showing an alert dialog with title, message, and two action buttons.
图 4. 一个带有标题、消息和两个操作按钮的警报对话框。

添加列表

The AlertDialog API 提供了三种列表

  • 一个传统的单选列表。
  • 一个持久的单选列表(单选按钮)。
  • 一个持久的复选框列表(复选框)。

要创建类似于图 5 中的单选列表,请使用 setItems() 方法


Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setItems(arrayOf("Item One", "Item Two", "Item Three")) { dialog, which ->
        // Do something on item tapped.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

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

此代码片段生成了以下对话框

An image showing a dialog with a title and list.
图 5. 一个带有标题和列表的对话框。

由于列表显示在对话框的内容区域,因此对话框不能同时显示消息和列表。 使用 setTitle() 为对话框设置标题。 要指定列表中的项,请调用 setItems(),并传入一个数组。 或者,您可以使用 setAdapter() 指定列表。 这允许您使用 ListAdapter 为列表提供动态数据(例如来自数据库的数据)。

如果使用 ListAdapter 为列表提供数据,请始终使用 Loader,以便内容异步加载。 这将在 使用适配器构建布局加载器 中进一步描述。

添加持久的复选框列表或单选列表

要添加复选框列表(复选框)或单选列表(单选按钮),请分别使用 setMultiChoiceItems()setSingleChoiceItems() 方法。

例如,以下是如何创建类似于图 6 中的复选框列表,该列表将选定的项保存到 ArrayList

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setMultiChoiceItems(
        arrayOf("Item One", "Item Two", "Item Three"), null) { dialog, which, isChecked ->
        // Do something.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

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 checks the item, add it to the selected
                       // items.
                       selectedItems.add(which);
                   } else if (selectedItems.contains(which)) {
                       // 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 taps OK, so save the selectedItems results
                   // somewhere or return them to the component that opens the
                   // dialog.
                   ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   ...
               }
           });

    return builder.create();
}
An image showing a dialog containing a list of multiple-choice items.
图 6. 一个复选框列表。

可以使用以下方式获取单选警报对话框

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setSingleChoiceItems(
        arrayOf("Item One", "Item Two", "Item Three"), 0
    ) { dialog, which ->
        // Do something.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

Java

        String[] choices = {"Item One", "Item Two", "Item Three"};
        
        AlertDialog.Builder builder = AlertDialog.Builder(context);
        builder
                .setTitle("I am the title")
                .setPositiveButton("Positive", (dialog, which) -> {

                })
                .setNegativeButton("Negative", (dialog, which) -> {

                })
                .setSingleChoiceItems(choices, 0, (dialog, which) -> {

                });

        AlertDialog dialog = builder.create();
        dialog.show();

这将导致以下示例

An image showing a dialog containing a list of single-choice items.
图 7. 一个单选列表。

创建自定义布局

如果你想要在对话框中使用自定义布局,请创建一个布局并通过调用setView()方法添加到AlertDialog中,该方法在你的AlertDialog.Builder对象上调用。

An image showing a custom dialog layout.
图 8. 自定义对话框布局。

默认情况下,自定义布局会填充对话框窗口,但你仍然可以使用AlertDialog.Builder方法添加按钮和标题。

例如,以下是在前面的自定义对话框布局的布局文件。

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>

要在你DialogFragment中加载布局,请使用LayoutInflater获得一个getLayoutInflater(),并调用inflate()。第一个参数是布局资源 ID,第二个参数是布局的父视图。然后,你可以调用setView()将布局放置在对话框中。以下示例演示了这一点。

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 it's 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 it's 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();
}

如果你想要自定义对话框,你也可以将Activity显示为对话框,而不是使用Dialog API。创建一个活动,并在<activity>清单元素中将它的主题设置为Theme.Holo.Dialog

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

现在活动将显示在对话框窗口中,而不是全屏显示。

将事件传递回对话框的主机

当用户点击对话框的某个操作按钮或从其列表中选择某个项目时,你的DialogFragment可能会自行执行必要的操作,但通常你希望将事件传递给打开对话框的活动或片段。为此,请定义一个接口,该接口包含每个类型点击事件的方法。然后,在接收来自对话框的操作事件的主机组件中实现该接口。

例如,以下是一个DialogFragment,它定义了一个接口,通过该接口将事件传递回主机活动。

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 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 you 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 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 you 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");
        }
    }
    ...
}

承载对话框的活动使用对话框片段的构造函数创建一个对话框实例,并通过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 taps the dialog's positive button.
    }

    override fun onDialogNegativeClick(dialog: DialogFragment) {
        // User taps 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 taps the dialog's positive button.
        ...
    }

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

由于主机活动实现了NoticeDialogListener(由前面的示例中显示的onAttach()回调方法强制执行),对话框片段可以使用接口回调方法将点击事件传递给活动。

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

显示对话框

当你想要显示对话框时,请创建一个你的DialogFragment实例并调用show(),将FragmentManager和对话框片段的标签名称作为参数传递。

你可以通过从FragmentActivity调用getSupportFragmentManager(),或者从Fragment调用getParentFragmentManager()来获取FragmentManager。以下是一个示例。

Kotlin

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

Java

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

第二个参数"game"是一个唯一的标签名称,系统在必要时使用它来保存和恢复片段状态。该标签还可以让你通过调用findFragmentByTag()来获取对片段的句柄。

全屏显示对话框或作为嵌入式片段显示对话框

你可能希望 UI 设计中的某个部分在某些情况下显示为对话框,而在其他情况下显示为全屏或嵌入式片段。你可能还希望它根据设备的屏幕尺寸以不同的方式显示。DialogFragment类提供了灵活性来完成此操作,因为它可以作为可嵌入的Fragment

但是,在这种情况下,你不能使用AlertDialog.Builder或其他Dialog对象来构建对话框。如果你希望DialogFragment可嵌入,请在布局中定义对话框的 UI,然后在onCreateView()回调中加载布局。

以下是一个示例DialogFragment,它可以使用名为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 a 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 the dialog characteristics. For example,
        // the dialog includes a title by default, but your custom layout might
        // not need it. 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 a 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 the dialog characteristics. For example,
        // the dialog includes a title by default, but your custom layout might
        // not need it. 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;
    }
}

以下示例根据屏幕尺寸确定是将片段显示为对话框还是全屏 UI。

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 polished look, 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 polished look, 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();
    }
}

有关执行片段事务的更多信息,请参阅片段

在此示例中,mIsLargeLayout布尔值指定当前设备是否必须使用应用程序的大布局设计,因此将此片段显示为对话框,而不是全屏显示。设置这种布尔值的最佳方法是使用bool 资源值声明一个具有针对不同屏幕尺寸的替代资源值的资源。例如,以下是针对不同屏幕尺寸的 bool 资源的两个版本。

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>

然后,你可以在活动的onCreate()方法中初始化mIsLargeLayout值,如以下示例所示。

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

在大屏幕上将活动显示为对话框

你可以在小屏幕上将对话框显示为全屏 UI,也可以通过在大屏幕上将Activity显示为对话框来获得相同的结果。你选择的方法取决于应用程序设计,但当应用程序为小屏幕设计时,将活动显示为对话框通常很有用,因为你希望通过将短暂的活动显示为对话框来改善平板电脑上的体验。

要仅在大屏幕上将活动显示为对话框,请将Theme.Holo.DialogWhenLarge主题应用于<activity>清单元素。

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

有关使用主题对活动进行样式设置的更多信息,请参阅样式和主题

关闭对话框

当用户点击使用AlertDialog.Builder创建的操作按钮时,系统会为你关闭对话框。

当用户点击对话框列表中的项目时,系统也会关闭对话框,除非该列表使用单选按钮或复选框。否则,你可以通过在你的DialogFragment上调用dismiss()来手动关闭对话框。

如果你需要在对话框消失时执行某些操作,可以在你的DialogFragment中实现onDismiss()方法。

你还可以取消对话框。这是一个特殊事件,表示用户在未完成任务的情况下离开对话框。如果用户点击后退按钮或点击对话框区域之外的屏幕,或者你明确地在Dialog上调用cancel()(例如,响应对话框中的“取消”按钮),就会发生这种情况。

如前面的示例所示,你可以通过在你的DialogFragment类中实现onCancel()来响应取消事件。