使用 DialogFragment 显示对话框

DialogFragment 是专为创建和托管对话框而设计的特殊片段子类。虽然您不需要在片段中托管对话框,但这样做可以让 FragmentManager 管理对话框的状态,并在发生配置变更时自动恢复对话框。

创建 DialogFragment

要创建 DialogFragment,请创建一个扩展 DialogFragment 的类,并覆盖 onCreateDialog(),如以下示例所示。

Kotlin

class PurchaseConfirmationDialogFragment : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
            AlertDialog.Builder(requireContext())
                .setMessage(getString(R.string.order_confirmation))
                .setPositiveButton(getString(R.string.ok)) { _,_ -> }
                .create()

    companion object {
        const val TAG = "PurchaseConfirmationDialog"
    }
}

Java

public class PurchaseConfirmationDialogFragment extends DialogFragment {
   @NonNull
   @Override
   public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
       return new AlertDialog.Builder(requireContext())
               .setMessage(getString(R.string.order_confirmation))
               .setPositiveButton(getString(R.string.ok), (dialog, which) -> {} )
               .create();
   }

   public static String TAG = "PurchaseConfirmationDialog";
}

onCreateView() 在普通片段中创建根 View 类似,onCreateDialog() 创建一个 Dialog 以作为 DialogFragment 的一部分显示。DialogFragment 处理在片段生命周期的适当状态下显示 Dialog

onCreateView() 一样,您可以从 onCreateDialog() 返回 Dialog 的任何子类,并且不限于使用 AlertDialog

显示 DialogFragment

您无需手动创建 FragmentTransaction 来显示您的 DialogFragment。相反,请使用 show() 方法来显示您的对话框。您可以传递对 FragmentManager 的引用和用作 FragmentTransaction 标记的 String

当从 Fragment 中创建 DialogFragment 时,请使用片段的子 FragmentManager,以便在配置变更后正确恢复状态。非空标记允许您使用 findFragmentByTag() 在稍后检索 DialogFragment

Kotlin

// From another Fragment or Activity where you wish to show this
// PurchaseConfirmationDialogFragment.
PurchaseConfirmationDialogFragment().show(
     childFragmentManager, PurchaseConfirmationDialog.TAG)

Java

// From another Fragment or Activity where you wish to show this
// PurchaseConfirmationDialogFragment.
new PurchaseConfirmationDialogFragment().show(
       getChildFragmentManager(), PurchaseConfirmationDialog.TAG);

为了更好地控制 FragmentTransaction,您可以使用接受现有 FragmentTransactionshow() 重载方法。

DialogFragment 生命周期

A DialogFragment 遵循标准片段生命周期,并具有一些额外的生命周期回调。最常见的如下所示:

  • onCreateDialog():覆盖此回调以提供一个 Dialog,供片段管理和显示。
  • onDismiss():如果您需要在 Dialog 关闭时执行任何自定义逻辑,例如释放资源或取消订阅可观察资源,请覆盖此回调。
  • onCancel():如果您需要在 Dialog 取消时执行任何自定义逻辑,请覆盖此回调。

DialogFragment 还包含用于关闭或设置 DialogFragment 可取消性的方法

  • dismiss():关闭片段及其对话框。如果片段已添加到返回栈,则返回栈中直至(包括)此条目之前的所有状态都将弹出。否则,将提交新的事务以移除片段。
  • setCancelable():控制显示的 Dialog 是否可取消。使用此方法而不是直接调用 Dialog.setCancelable(boolean)

当使用带有 DialogDialogFragment 时,您不会覆盖 onCreateView()onViewCreated()。对话框不仅仅是视图——它们有自己的窗口。因此,仅仅覆盖 onCreateView() 是不够的。此外,除非您已覆盖 onCreateView() 并提供了非空视图,否则 onViewCreated() 永远不会在自定义 DialogFragment 上调用。

使用自定义视图

您可以创建一个 DialogFragment 并通过覆盖 onCreateView() 来显示对话框。您可以像典型的片段一样为其指定一个 layoutId,或者使用 DialogFragment 构造函数

onCreateView() 返回的 View 会自动添加到对话框中。在大多数情况下,这意味着您不需要覆盖 onCreateDialog(),因为默认的空对话框会填充您的视图。

某些 DialogFragment 的子类,例如 BottomSheetDialogFragment,会将您的视图嵌入到样式为底部工作表的对话框中。