จะปิด DialogFragment ได้อย่างไร?


121

เอกสารพูดสิ่งนี้สำหรับdismiss()วิธีการจากDialogคลาส:

ปิดกล่องโต้ตอบนี้และลบออกจากหน้าจอ วิธีนี้สามารถเรียกใช้ได้อย่างปลอดภัยจากเธรดใด ๆ โปรดทราบว่าคุณไม่ควรแทนที่เมธอดนี้เพื่อทำการล้างข้อมูลเมื่อกล่องโต้ตอบถูกปิดใช้แทนใช้ในonStop().

ในรหัสของฉันสิ่งที่ฉันทำคือเรียกร้องgetDialog().dismiss()ให้ปิด onStop()แต่ผมไม่ได้ทำอะไรอย่างอื่นหรือแม้กระทั่งการใช้ ดังนั้นฉันจึงถามว่าจะยกเลิก a อย่างไรให้ถูกต้องDialogFragmentเพื่อหลีกเลี่ยงการรั่วไหลของหน่วยความจำ ฯลฯ

คำตอบ:


197

TL; DR:วิธีที่ถูกต้องใกล้ชิดDialogFragmentคือการใช้dismiss() โดยตรงบน DialogFragment


รายละเอียด : เอกสารของสถานะDialogFragment

การควบคุมกล่องโต้ตอบ (ตัดสินใจว่าจะแสดงซ่อนปิดเมื่อใด) ควรดำเนินการผ่าน API ที่นี่ไม่ใช่ด้วยการเรียกโดยตรงในกล่องโต้ตอบ

ดังนั้นคุณไม่ควรใช้getDialog().dismiss()ตั้งแต่ที่จะเรียกใช้ในการโต้ตอบdismiss() คุณควรใช้dismiss()วิธีการของ DialogFragment แทน:

โมฆะสาธารณะปิด ()

ปิดส่วนย่อยและกล่องโต้ตอบ หากมีการเพิ่มแฟรกเมนต์ลงในแบ็กสแต็กสถานะแบ็กสแต็กทั้งหมดที่มีค่าสูงสุดและรวมรายการนี้จะแสดง มิฉะนั้นธุรกรรมใหม่จะมุ่งมั่นที่จะลบส่วน

อย่างที่คุณเห็นสิ่งนี้ไม่เพียงดูแลการปิดกล่องโต้ตอบ แต่ยังรวมถึงการจัดการธุรกรรมส่วนที่เกี่ยวข้องในกระบวนการด้วย

คุณจะต้องใช้ก็ต่อonStopเมื่อคุณสร้างทรัพยากรใด ๆ อย่างชัดเจนที่ต้องใช้การล้างข้อมูลด้วยตนเอง (การปิดไฟล์การปิดเคอร์เซอร์ ฯลฯ ) ถึงอย่างนั้นฉันจะแทนที่onStopDialogFragment แทนที่จะonStopเป็น Dialog ที่อยู่ข้างใต้


1
@ScootrNova: ไม่ควรคุณอาจมีข้อผิดพลาดที่อื่น คุณสร้างส่วนอย่างไร
Heinzi

protected void showDialogFragment(final DialogFragment fragment) {final FragmentTransaction fTransaction = getSupportFragmentManager().beginTransaction(); fTransaction.addToBackStack(null); fragment.show(fTransaction, "dialog");} ขออภัยซับอันเดียวที่น่ารังเกียจ! แต่ใช่คุณพูดถูกดังนั้นในขณะนี้ฉันได้เขียนวิธีอื่นในการปิด DialogFragments ของฉัน วิธีที่ฉันไล่พวกเขาโดยใช้เมธอดการปิด () คือการค้นหาแฟรกเมนต์ตามแท็กจากนั้นจึงเรียกใช้การปิด () หากไม่เป็นโมฆะ โอ้ใช่ฉันกำลังnewหาชิ้นส่วนก่อนที่จะส่งต่อไปยังวิธีนั้น
Charles Madere

2
@ScootrNova: อืมไม่เห็นมีอะไรผิดปกติในทางกลับกันฉันไม่เคยใช้ไลบรารีความเข้ากันได้ดังนั้นฉันจึงไม่แน่ใจในเรื่องนั้น บางทีมันอาจจะสมเหตุสมผลที่จะสร้างตัวอย่างที่เรียบง่ายและมีอยู่ในตัวเองและเริ่มคำถามใหม่ในเรื่องนั้น
Heinzi

@CharlesMadere ในสมัยนั้นคุณหาทางแก้ไขหรือยัง?
JCarlosR

ขอโทษ @JCarlos นี่เป็นปีที่แล้วฉันไม่แน่ใจ
Charles Madere

76

ฉันคิดว่าวิธีที่ดีกว่าในการปิด a DialogFragmentคือ:

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

วิธีนี้ทำให้คุณไม่ต้องอ้างอิงถึงDialogFragmentและสามารถปิดได้จากทุกที่


7

ทำไมคุณไม่ลองใช้เฉพาะรหัสนี้:

dismiss();

หากคุณต้องการปิด Dialog Fragment ด้วยตัวเอง คุณสามารถใส่รหัสนี้ในส่วนของกล่องโต้ตอบที่คุณต้องการปิดกล่องโต้ตอบ

ตัวอย่างเช่น:

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

การดำเนินการนี้จะปิด Dialog Fragment ล่าสุดที่แสดงบนหน้าจอ

หวังว่าจะช่วยให้คุณ


ไม่ทำงานตลอดเวลา
Mahmoud Heretani

5

ฉันให้คะแนนโหวตสำหรับคำตอบของ Terel ฉันแค่ต้องการโพสต์สิ่งนี้สำหรับผู้ใช้ Kotlin:

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

รหัสง่ายๆทำงานยากขอบคุณสำหรับการอัพเดทเพื่อน !!
Ayush Katuwal


1

คุณควรยกเลิกคุณDialogในonPause()เพื่อแทนที่

ก่อนที่จะปิดคุณสามารถตรวจสอบnullและแสดงดังตัวอย่างด้านล่าง:

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

เขาได้เขียนไว้แล้วว่าเขากำลังทำการปิด () และเกี่ยวกับ DialogFragment
Paresh Mayani

ฉันคิดว่ามันใช้ได้กับทั้ง Dialog และ DialogFragments @PareshMayani
Venky

2
ฉันเชื่อว่า @PareshMayani ถูกต้อง Venky บทช่วยสอนDialogFragmentโดย google ไม่แสดงonPause()วิธีการที่ใช้เลย แต่ฉันคิดว่าฉันเห็นสิ่งที่คุณกำลังทำอยู่ มีประเด็นอะไรonPause()บ้างถ้าผู้ใช้ไม่โทร นั่นคือเมื่อระบบรู้ว่าชิ้นส่วนถูกเรียกออกไป แล้วผู้ใช้จะยกเลิกเมื่อใด มีวิธีใดที่ดีกว่าในการปิดมันในกรณีนี้
Andy

1

มีการอ้างอิงถึงเอกสารอย่างเป็นทางการ ( 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 ปัจจุบันและกล่องโต้ตอบจะถูกทำลายและรายการก่อนหน้านี้ (ถ้ามี) จะแสดงขึ้นมาใหม่ โปรดทราบว่าในกรณีนี้ DialogFragment จะดูแลการเปิดธุรกรรมของกล่องโต้ตอบจะถูกปิดแยกต่างหากจากมัน

สำหรับความต้องการของฉันฉันเปลี่ยนเป็น:

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

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

1

การเพิ่มคำตอบอื่น ๆ เมื่อมีการDialogFragmentโทรแบบเต็มหน้าจอdismiss()จะไม่ทำให้ DialogFragment ปรากฏขึ้นจากส่วนหลังของแฟรกเมนต์ วิธีแก้ปัญหาคือการเรียกonBackPressed()ใช้กิจกรรมหลัก

สิ่งนี้:

CustomDialogFragment.kt

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

บันทึกวันนี้ขอบคุณมาก
Mahmoud Heretani

0

เพียงแค่เรียกการปิด () จากส่วนที่คุณต้องการปิด

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

0

ฉันพบว่าเมื่อมีการกำหนด<fragment>แฟรกเมนต์ของฉันในกราฟการนำทางด้วยแท็ก (สำหรับไดอะล็อกแฟรกเต็มหน้าจอ) ไดอะล็อกแฟรกเมนต์จะไม่ปิดด้วยdismiss()คำสั่ง แต่ฉันต้องเปิดกองหลัง:

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

อย่างไรก็ตามหากมีการกำหนดส่วนโต้ตอบเดียวกันในกราฟการนำทางด้วย<dialog>แท็กก็dismiss()ใช้ได้ดี


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.