Android 如何正确关闭 DialogFragment?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11201022/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:18:03  来源:igfitidea点击:

How to correctly dismiss a DialogFragment?

androidandroid-dialogfragment

提问by Andy

The docs say this for the dismiss()method from the Dialogclass:

文档dismiss()Dialog类中的方法是这样说的:

Dismiss this dialog, removing it from the screen. This method can be invoked safely from any thread. Note that you should not override this method to do cleanup when the dialog is dismissed, instead implement that in onStop().

关闭此对话框,将其从屏幕上移除。可以从任何线程安全地调用此方法。请注意,当对话框关闭时,您不应覆盖此方法来进行清理,而是在onStop().

In my code, all I do is call getDialog().dismiss()to dismiss it. But I am not doing anything else or even using onStop(). So I am asking exactly how to correctly dismiss a DialogFragmentto avoid any memory leaks, etc..

在我的代码中,我所做的就是调用getDialog().dismiss()关闭它。但我没有做任何其他事情,甚至没有使用onStop(). 所以我问的是如何正确地解除 aDialogFragment以避免任何内存泄漏等。

回答by Heinzi

tl;dr:The correct way to close a DialogFragmentis to use dismiss()directly on the DialogFragment.

tl;dr:关闭 a 的正确方法DialogFragmentdismiss()直接在 DialogFragment 上使用。



Details: The documentation of DialogFragmentstates

详细信息DialogFragment状态的文档

Control of the dialog (deciding when to show, hide, dismiss it) should be done through the API here, not with direct calls on the dialog.

对话框的控制(决定何时显示、隐藏、关闭)应该通过这里的 API 来完成,而不是直接调用对话框。

Thus, you should not use getDialog().dismiss(), since that would invoke dismiss()on the dialog. Instead, you should use the dismiss()method of the DialogFragment itself:

因此,您不应使用getDialog().dismiss(),因为这会dismiss()在对话框上调用。相反,您应该使用dismiss()DialogFragment 本身的方法:

public void dismiss()

Dismiss the fragment and its dialog. If the fragment was added to the back stack, all back stack state up to and including this entry will be popped. Otherwise, a new transaction will be committed to remove the fragment.

公共无效解雇()

关闭片段及其对话框。如果片段被添加到后退堆栈,则直到并包括此条目的所有后退堆栈状态都将被弹出。否则,将提交一个新事务以删除该片段。

As you can see, this takes care not only of closing the dialog but also of handling the fragment transactions involved in the process.

如您所见,这不仅负责关闭对话框,还负责处理流程中涉及的片段事务。

You only need to use onStopif you explicitly created any resources that require manual cleanup (closing files, closing cursors, etc.). Even then, I would override onStopof the DialogFragment rather than onStopof the underlying Dialog.

onStop当您明确创建任何需要手动清理的资源(关闭文件、关闭游标等)时才需要使用。即便如此,我也会覆盖onStopDialogFragment 而不是onStop底层 Dialog。

回答by Terel

I think a better way to close a DialogFragmentis this:

我认为关闭 a 的更好方法DialogFragment是:

Fragment prev = getSupportFragmentManager().findFragmentByTag("fragment_dialog");
if (prev != null) {
    DialogFragment df = (DialogFragment) prev;
    df.dismiss();
}

This way you dont have to hold a reference to the DialogFragmentand can close it from everywhere.

这样您就不必持有对 的引用,DialogFragment并且可以从任何地方关闭它。

回答by Shiva Tiwari

Why don't you try using only this code:

为什么不尝试仅使用此代码:

dismiss();

If you want to dismiss the Dialog Fragment by its own. You can simply put this code inside the dialog fragment where you want to dismiss the Dialog.

如果您想自行关闭对话框片段。您可以简单地将此代码放在要关闭对话框的对话框片段中。

For example:

例如:

button.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       dismiss();
   }
});

This will close the recent Dialog Fragment that is shown on the screen.

这将关闭屏幕上显示的最近的对话框片段。

Hope it helps for you.

希望对你有帮助。

回答by JustinMorris

I gave an upvote to Terel's answer. I just wanted to post this for any Kotlin users:

我对特雷尔的回答表示赞同。我只是想为任何 Kotlin 用户发布这个:

supportFragmentManager.findFragmentByTag(TAG_DIALOG)?.let {
    (it as DialogFragment).dismiss()
}

回答by Phil

Kotlin Versionof Terel answer

Kotlin 版本的 Terel 答案

(fragmentManager.findFragmentByTag(TAG) as? DialogFragment)?.dismiss()

回答by Venky

You should dismiss you Dialogin onPause()so override it.

你应该解雇你DialogonPause()所以覆盖它。

Also before dismissing you can check for nulland is showing like below snippet:

同样在解雇之前,您可以检查null并显示如下片段:

@Override
protected void onPause() {
    super.onPause();
    if (dialog != null && dialog.isShowing()) {
        dialog.dismiss();
    }
}

回答by Maksim Ivanov

There are references to the official docs (DialogFragment Reference) in other answers, but no mention of the example given there:

在其他答案中有对官方文档(DialogFragment Reference)的引用,但没有提到那里给出的示例:

void showDialog() {
    mStackLevel++;

    // DialogFragment.show() will take care of adding the fragment
    // in a transaction.  We also want to remove any currently showing
    // dialog, so make our own transaction and take care of that here.
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    Fragment prev = getFragmentManager().findFragmentByTag("dialog");
    if (prev != null) {
        ft.remove(prev);
    }
    ft.addToBackStack(null);

    // Create and show the dialog.
    DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);
    newFragment.show(ft, "dialog");
}

This removes any currently shown dialog, creates a new DialogFragment with an argument, and shows it as a new state on the back stack. When the transaction is popped, the current DialogFragment and its Dialog will be destroyed, and the previous one (if any) re-shown. Note that in this case DialogFragment will take care of popping the transaction of the Dialog is dismissed separately from it.

这将删除任何当前显示的对话框,创建一个带有参数的新 DialogFragment,并将其显示为返回堆栈上的新状态。当事务弹出时,当前的 DialogFragment 及其 Dialog 将被销毁,并重新显示前一个(如果有)。请注意,在这种情况下,DialogFragment 将负责弹出 Dialog 的事务,并与它分开解散。

For my needs I changed it to:

根据我的需要,我将其更改为:

FragmentManager manager = getSupportFragmentManager();
Fragment prev = manager.findFragmentByTag(TAG);
if (prev != null) {
    manager.beginTransaction().remove(prev).commit();
}

MyDialogFragment fragment = new MyDialogFragment();
fragment.show(manager, TAG);

回答by jon

I found that when my fragment was defined in the navigation graph with a <fragment>tag (for a full screen dialogfragment), the dialogfragment would not dismiss with the dismiss()command. Instead, I had to pop the back stack:

我发现当我的片段在导航图中用<fragment>标签定义时(对于全屏对话框片段),对话框片段不会用dismiss()命令关闭。相反,我不得不弹出返回堆栈:

findNavController(getActivity(), R.id.nav_host_fragment).popBackStack();

However, if the same dialogfragment was defined in the navigation graph with a <dialog>tag, dismiss()works fine.

但是,如果在导航图中使用<dialog>标记定义了相同的对话框片段,则dismiss()工作正常。

回答by Victor Odiah

CustomFragment dialog = (CustomDataFragment) getSupportFragmentManager().findFragmentByTag("Fragment_TAG");
if (dialog != null) {
  dialog.dismiss();
}

回答by mikehc

Adding to the other answers, when having a DialogFragmentthat is full screen calling dismiss()won't pop the DialogFragment from the fragment backstack. A workaround is to call onBackPressed()on the parent activity.

添加到其他答案中,当进行DialogFragment全屏调用dismiss()时,不会从片段后台堆栈中弹出 DialogFragment。一种解决方法是调用onBackPressed()父活动。

Something like this:

像这样的东西:

CustomDialogFragment.kt

CustomDialogFragment.kt

closeButton.onClick {
    requireActivity().onBackPressed()
}