[英]How to correctly dismiss a DialogFragment?
文檔針對Dialog
類中的dismiss()
方法說了這一點:
關閉此對話框,將其從屏幕上移除。 可以從任何線程安全地調用此方法。 請注意,當對話框關閉時,您不應覆蓋此方法來進行清理,而應在
onStop()
中實現該方法。
在我的代碼中,我所做的就是調用getDialog().dismiss()
來關閉它。 但我沒有做任何其他事情,甚至沒有使用onStop()
。 所以我問的是如何正確關閉DialogFragment
以避免任何內存泄漏等。
tl;dr:關閉DialogFragment
的正確方法是直接在 DialogFragment 上使用dismiss()
。
詳細信息: DialogFragment 說明的文檔
對話框的控制(決定何時顯示、隱藏、關閉它)應該通過此處的 API 完成,而不是直接調用對話框。
因此,您不應使用getDialog().dismiss()
,因為那樣會在 dialog 上調用dismiss()
。 相反,您應該使用 DialogFragment 本身的dismiss()
方法:
公共無效解雇()
關閉片段及其對話框。 如果片段被添加到返回堆棧,所有返回堆棧狀態直到並包括這個條目將被彈出。 否則,將提交一個新的事務來刪除片段。
如您所見,這不僅會關閉對話框,還會處理流程中涉及的片段事務。
如果您顯式創建了任何需要手動清理的資源(關閉文件、關閉游標等),則只需要使用onStop
。 即使那樣,我也會重寫 DialogFragment 的onStop
而不是基礎 Dialog 的onStop
。
我認為關閉DialogFragment
的更好方法是:
Fragment prev = getSupportFragmentManager().findFragmentByTag("fragment_dialog");
if (prev != null) {
DialogFragment df = (DialogFragment) prev;
df.dismiss();
}
這樣您就不必持有對DialogFragment
的引用,並且可以從任何地方關閉它。
為什么不嘗試僅使用此代碼:
dismiss();
如果您想自己關閉對話框片段。 您可以簡單地將此代碼放在要關閉對話框的對話框片段中。
例如:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
這將關閉屏幕上顯示的最近的對話框片段。
希望對你有幫助。
我贊成特雷爾的回答。 我只想為任何 Kotlin 用戶發布這個:
supportFragmentManager.findFragmentByTag(TAG_DIALOG)?.let {
(it as DialogFragment).dismiss()
}
Terel 答案的Kotlin 版本
(fragmentManager.findFragmentByTag(TAG) as? DialogFragment)?.dismiss()
您應該在onPause()
中關閉Dialog
,以便覆蓋它。
同樣在解散之前,您可以檢查null
並顯示如下代碼片段:
@Override
protected void onPause() {
super.onPause();
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
在其他答案中有對官方文檔( 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");
}
這將刪除任何當前顯示的對話框,創建一個帶有參數的新 DialogFragment,並將其顯示為返回堆棧上的新狀態。 當事務彈出時,當前的 DialogFragment 及其 Dialog 將被銷毀,並重新顯示之前的(如果有的話)。 請注意,在這種情況下,DialogFragment 將負責彈出 Dialog 的事務,與它分開處理。
為了我的需要,我將其更改為:
FragmentManager manager = getSupportFragmentManager();
Fragment prev = manager.findFragmentByTag(TAG);
if (prev != null) {
manager.beginTransaction().remove(prev).commit();
}
MyDialogFragment fragment = new MyDialogFragment();
fragment.show(manager, TAG);
我發現當我的片段在導航圖中用<fragment>
標簽定義時(對於全屏對話框片段),對話框片段不會用dismiss()
命令關閉。 相反,我不得不彈出返回堆棧:
findNavController(getActivity(), R.id.nav_host_fragment).popBackStack();
但是,如果在帶有<dialog>
標記的導航圖中定義了相同的 dialogfragment,則dismiss()
可以正常工作。
CustomFragment dialog = (CustomDataFragment) getSupportFragmentManager().findFragmentByTag("Fragment_TAG");
if (dialog != null) {
dialog.dismiss();
}
添加到其他答案中,當具有全屏調用dismiss()
的DialogFragment
時,不會從片段后台彈出 DialogFragment。 解決方法是在父活動上調用onBackPressed()
。
像這樣:
自定義對話框片段.kt
closeButton.onClick {
requireActivity().onBackPressed()
}
只需從要關閉的片段中調用 dismiss() 即可。
imageView3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
考慮下面的示例代碼片段,它演示了如何安全地關閉對話框片段:
DialogFragment dialogFragment = new DialogFragment();
/**
* do something
*/
// Now you want to dismiss the dialog fragment
if (dialogFragment.getDialog() != null && dialogFragment.getDialog().isShowing())
{
// Dismiss the dialog
dialogFragment.dismiss();
}
快樂編碼!
這是一個簡單的 AppCompatActivity 擴展函數,它關閉打開的對話框片段:
fun AppCompatActivity.whenDialogOpenDismiss(
tag: String
) {
supportFragmentManager.findFragmentByTag(tag)?.let {
if(it is DialogFragment) it.dismiss() }
}
當然,您可以直接從任何活動中調用它。 如果您需要從 Fragment 調用它,只需對 Fragment 類創建相同的擴展函數
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.