ป้องกันกล่องโต้ตอบกิจกรรม Android จากการปิดเมื่อสัมผัสภายนอก


228

ฉันมีกิจกรรมที่ใช้สไตล์ Theme.Dialog ว่าเป็นหน้าต่างลอยเหนือกิจกรรมอื่น อย่างไรก็ตามเมื่อฉันคลิกนอกหน้าต่างข้อความ (ในกิจกรรมพื้นหลัง) กล่องโต้ตอบจะปิดลง ฉันจะหยุดพฤติกรรมนี้ได้อย่างไร


1
ทำไมคุณถึงทำเช่นนั้น หากพฤติกรรมที่คุณต้องการเป็นของกล่องโต้ตอบทำไมไม่ใช้กล่องโต้ตอบ? สำหรับคำถามของคุณฉันไม่คิดว่าจะมีวิธีแก้ปัญหาสำหรับเรื่องนี้
Kumar Bibek

กล่องโต้ตอบ @KumarBibek ถูก จำกัด เมื่อมันมาถึงการปรับแต่งรูปแบบ ... นั่นเป็นเหตุผลที่กิจกรรม แม้แต่เอกสารสำหรับนักพัฒนาก็แนะนำวิธีนี้สำหรับการปรับแต่งที่ยืดหยุ่น
Leo

1
และสิ่งที่ OP ต้องการคือไดอะล็อกModalเช่นไดอะล็อกที่บังคับให้ผู้ใช้ตอบเช่น OK หรือ Yes / No ผู้ใช้ไม่ควรคลิกไป
Scott Biggs

คำตอบ:


33

สิ่งนี้จะช่วยคุณได้ มันเป็นวิธีที่จะจัดการกับเหตุการณ์สัมผัสภายนอก:

วิธียกเลิก Dialog ที่มีธีมเช่นกิจกรรมเมื่อถูกสัมผัสนอกหน้าต่างได้อย่างไร?

ฉันคิดว่าคุณสามารถป้องกันการปิดได้ แต่สิ่งที่เป็น แต่ที่แปลกก็คือว่าการทำงานเริ่มต้นของการโต้ตอบกิจกรรมของคุณควรจะเป็นไม่ได้ที่จะปิดตัวเองเมื่อคุณสัมผัสนอก

(PS: รหัสใช้ WindowManager.LayoutParams)


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

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

4
ซึ่งเป็นสิ่งที่เขาอธิบายด้วย "โดยการจับเหตุการณ์และไม่ทำอะไรเลยฉันคิดว่าคุณสามารถป้องกันการปิด"
metter

4
ด้วยเหตุผลบางอย่างหลังจากทำทั้ง FLAG_NOT_MODAL ทั้งหมด WATCH_OUTSIDE_TOUCH การสัมผัสภายนอกนั้นไม่ได้ปิดกิจกรรม แต่คลิกปุ่มด้านหลังของกิจกรรม ความคิดใด ๆ
njzk2

โปรดทราบว่ากล่องโต้ตอบมีเงา (อย่างน้อยก็จนถึงตอนนี้ (8.0)): หากคุณคลิกที่เงา Android จะตีความการคลิกนั้นเหมือนในกล่องโต้ตอบ แค่อยากจะแบ่งปันสิ่งนี้กับโลกมันใช้เวลา 10 นาทีกว่าจะได้มัน
Lorenzo Von Matterhorn

458

เพื่อป้องกันไม่ให้กล่องโต้ตอบถูกไล่ออกจากปุ่มย้อนกลับกดใช้สิ่งนี้

dialog.setCancelable(false);

และเพื่อป้องกันกล่องโต้ตอบจากการถูกไล่ออกนอกสัมผัสใช้สิ่งนี้

 dialog.setCanceledOnTouchOutside(false);

4
คำตอบนี้มีประโยชน์ แต่คำถามนี้เกี่ยวกับกิจกรรมที่ใช้คุณสมบัติ Theme.Dialog
Paresh Mayani

15
ฉันรู้ว่าเมื่อฉันรู้ว่ามันสายเกินไปเพราะมันช่วยคนจำนวนมากดังนั้นอย่าลบมัน
Singhak

12
ฉันรู้ว่านี่ไม่เกี่ยวข้องกับคำถามจริงๆ แต่สิ่งนี้ช่วยฉันได้ ขอบคุณ!
dennisdrew

5
นี่คือคำตอบที่ดีที่สุด ฉันสงสัยว่าคนส่วนใหญ่ที่พบคำถามนี้กำลังมองหาวิธีในการป้องกันไม่ให้มาตรฐานAlertDialogปิดการสัมผัสด้านนอกและนั่นคือสิ่งที่คำตอบนี้ให้
59

20
ใน AlertDialog เวอร์ชั่นใหม่กว่าคุณต้องใช้เท่านั้นsetCancelable(false)
Kobi Tate

120

สิ่งที่คุณมีจริง ๆ คือกิจกรรม (แม้ว่าจะดูเหมือนเป็นกล่องโต้ตอบ) ดังนั้นคุณควรโทรsetFinishOnTouchOutside(false)จากกิจกรรมของคุณหากคุณต้องการให้มันเปิดเมื่อมีการคลิกกิจกรรมพื้นหลัง

แก้ไข: ใช้งานได้กับ android API ระดับ 11 ขึ้นไปเท่านั้น


4
สิ่งนี้ไม่ได้ป้องกันคุณจากการกดปุ่ม "ย้อนกลับ" ในกิจกรรมของคุณ ดังนั้นคุณต้องแทนที่onBackPressed()การไม่ทำอะไรเลยในร่างกาย
Alex Bonel

มันไม่ได้ป้องกันปุ่ม "ย้อนกลับ" ในกล่องโต้ตอบกิจกรรมโดยไม่มี onBackPressed () ทำงานได้สมบูรณ์แบบด้วยสิ่งนี้ setFinishOnTouchOutside (false)
Kunalxigxag

68

สิ่งที่ใช้ได้ผลสำหรับฉันคือการสร้างDialogFragmentชุดที่ไม่สามารถยกเลิกได้:

dialog.setCancelable(false);

1
ไม่เป็นประโยชน์ คำถามนี้เกี่ยวกับกิจกรรมไม่ใช่กล่องโต้ตอบ
Scott Biggs

20

เมื่อใช้กล่องโต้ตอบเป็นกิจกรรมใน onCreate ให้เพิ่มสิ่งนี้

setFinishOnTouchOutside(false);

17

สำหรับ API 10 ที่สูงขึ้นกล่องโต้ตอบจะหายไปเมื่อแตะที่นอกขณะที่ต่ำกว่า API 11 กล่องโต้ตอบจะไม่หายไป เพื่อป้องกันสิ่งนี้คุณต้องทำ:

ในstyles.xml:<item name="android:windowCloseOnTouchOutside">false</item>

หรือ

ในonCreate()วิธีการใช้:this.setFinishOnTouchOutside(false);

หมายเหตุ: สำหรับ API 10 และต่ำกว่าวิธีนี้ไม่มีผลและไม่จำเป็น


14

การตั้งค่าการยกเลิกกล่องโต้ตอบเป็นเท็จนั้นเพียงพอแล้วและคุณแตะที่นอกกรอบโต้ตอบการแจ้งเตือนหรือคลิกที่ปุ่มย้อนกลับจะทำให้กล่องโต้ตอบแจ้งเตือนหายไป ดังนั้นใช้อันนี้:

setCancelable(false)

และฟังก์ชั่นอื่น ๆ ไม่จำเป็นอีกต่อไป: dialog.setCanceledOnTouchOutside(false);

หากคุณกำลังสร้างกล่องโต้ตอบชั่วคราวและสงสัยว่าจะใส่รหัสบรรทัดนี้ไว้นี่คือตัวอย่าง:

new AlertDialog.Builder(this)
                        .setTitle("Trial Version")
                        .setCancelable(false)
                        .setMessage("You are using trial version!")
                        .setIcon(R.drawable.time_left)
                        .setPositiveButton(android.R.string.yes, null).show();

12

ใช้รหัสนี้ใช้งานได้สำหรับฉัน

 AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
 alertDialog.setCancelable(false);


นี่ควรเป็นคำตอบที่ถูกต้องหากเขาสามารถทำคำถามที่ถูกต้องได้!
alijunior

2
นี่จะเป็นคำตอบที่ถูกต้องถ้า OP ถามถึงบทสนทนา ! แต่คำถามเกี่ยวกับกิจกรรม - ค่อนข้างแตกต่างกัน
Scott Biggs

11
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true); 
//use this to dismiss the dialog on outside click of dialog

dialog.setCanceledOnTouchOutside(false);
//use this for not to dismiss the dialog on outside click of dialog.

ดูลิงค์นี้สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการโต้ตอบ

dialog.setCancelable(false);
//used to prevent the dismiss of dialog on backpress of that activity

dialog.setCancelable(true);
//used to dismiss the dialog on onbackpressed of that activity

โปรดทราบว่าคำถามเกี่ยวข้องกับกิจกรรมที่ใช้เป็นบทสนทนาไม่ใช่คลาสโต้ตอบ
Scott Biggs

8

เพียงแค่

alertDialog.setCancelable(false);

ป้องกันไม่ให้ผู้ใช้คลิกนอกกล่องโต้ตอบ


6

กล่องโต้ตอบการแจ้งเตือนเลิกใช้แล้วดังนั้นให้ใช้กล่องโต้ตอบโต้ตอบ = กล่องโต้ตอบใหม่ (นี่);

เพื่อป้องกันการสัมผัสด้านนอกอย่างใกล้ชิด

dialog.setCanceledOnTouchOutside(false);

5

ใช้setFinishOnTouchOutside(false)สำหรับ API> 11 และไม่ต้องกังวลเพราะพฤติกรรมเริ่มต้นของแอนดรอยด์ที่กล่องโต้ตอบชุดรูปแบบกิจกรรมจะไม่ได้รับการติดต่อจากภายนอกสำหรับ API <11 :) !! ไชโย !!


5

ฉันใช้สิ่งนี้ใน onCreate () ดูเหมือนว่าจะใช้งานได้กับ Android ทุกรุ่น ทดสอบบน 5.0 และ 4.4.x ไม่สามารถทดสอบ Gingerbread ได้อุปกรณ์ Samsung (หมายเหตุ 1 ใช้ GB) มีวิธีนี้เป็นค่าเริ่มต้น:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    {
        setFinishOnTouchOutside(false);
    }
    else
    {
        getWindow().clearFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
    }

    super.onCreate(savedInstanceState);

4
        alert.setCancelable(false);
        alert.setCanceledOnTouchOutside(false);

ฉันเดาว่าสิ่งนี้จะช่วยคุณได้ผลสำหรับฉัน


1
โปรดลองอธิบายว่าทำไมสิ่งนี้ถึงได้ผล ... การถ่ายโอนข้อมูลรหัสไม่ใช่คำตอบที่ดี
Codebender


2

นอกจากนี้ยังเป็นไปได้ที่จะมอบหมายการดำเนินการที่แตกต่างกันในการใช้ onCancelListener:

alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener(){                   
    @Override
    public void onCancel(DialogInterface dialogInterface) {
        //Your custom logic
    } 
});

ฉันจะระบุได้อย่างไรว่าการยกเลิกถูกเรียกเนื่องจากการแตะนอกกรอบข้อความเตือน
cegprakash

มีประโยชน์มากในการสร้างการกระทำที่กำหนดเองเมื่อแตะนอกกรอบข้อความแจ้งเตือน!
Adam S.

1

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


1

builder.setCancelable (false);


โมฆะสาธารณะ Mensaje (ดู v) {

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("¿Quieres ir a el Menú principal?");
    builder.setMessage("Al presionar SI iras a el menú y saldras de la materia.");
    builder.setPositiveButton("SI", null);
    builder.setNegativeButton("NO", null);
    builder.setCancelable(false);
    builder.show();
}

1
สวัสดีอเล็กซ์. ยินดีต้อนรับสู่ StackOverflow และขอบคุณสำหรับคำตอบของคุณ คุณช่วยแก้ไขคำตอบของคุณเพื่ออธิบายว่าโค้ดของคุณทำอะไรได้บ้างและวิธีนี้แก้ปัญหาของ OP ได้หรือไม่? รหัสคำตอบเพียงมีกำลังใจที่พวกเขาไม่ได้สอนหรืออธิบายว่าทำไม ขอบคุณ!
ทิมมาโลน

-1

นี่คือคำตอบที่สมบูรณ์แบบสำหรับทุกคำถามของคุณ .... หวังว่าคุณจะสนุกกับการเขียนโค้ดใน Android

new AlertDialog.Builder(this)
            .setTitle("Akshat Rastogi Is Great")
            .setCancelable(false)
            .setMessage("I am the best Android Programmer")
            .setPositiveButton("I agree", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();

                }
            })
            .create().show();

ขอขอบคุณสำหรับข้อมูลโค้ดนี้ซึ่งอาจให้ความช่วยเหลือแบบ จำกัด และทันที คำอธิบายที่เหมาะสมจะช่วยเพิ่มมูลค่าในระยะยาวได้อย่างมากโดยการแสดงว่าทำไมนี่จึงเป็นทางออกที่ดีสำหรับปัญหาและจะทำให้มีประโยชน์มากขึ้นสำหรับผู้อ่านในอนาคตด้วยคำถามอื่น ๆ ที่คล้ายกัน โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายรวมถึงข้อสมมติฐานที่คุณทำ
Maximilian Peters
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.