วิธีป้องกันการปิดกล่องโต้ตอบเมื่อคลิกปุ่ม


732

ฉันมีกล่องโต้ตอบEditTextสำหรับการป้อนข้อมูล เมื่อฉันคลิกปุ่ม "ใช่" บนกล่องโต้ตอบมันจะตรวจสอบอินพุตและปิดกล่องโต้ตอบ อย่างไรก็ตามหากอินพุตผิดฉันต้องการคงอยู่ในกล่องโต้ตอบเดียวกัน ทุกครั้งไม่ว่าอินพุตจะเป็นอย่างไรกล่องโต้ตอบควรปิดโดยอัตโนมัติเมื่อฉันคลิกที่ปุ่ม "ไม่" ฉันจะปิดการใช้งานนี้ได้อย่างไร โดยวิธีการที่ฉันได้ใช้ PositiveButton และ NegativeButton สำหรับปุ่มในการโต้ตอบ

คำตอบ:


916

แก้ไข:ใช้งานได้เฉพาะกับ API 8+ ตามที่ระบุไว้โดยความคิดเห็นบางส่วน

นี่เป็นคำตอบที่ล่าช้า แต่คุณสามารถเพิ่ม onShowListener ใน AlertDialog ซึ่งคุณสามารถแทนที่ onClickListener ของปุ่มได้

final AlertDialog dialog = new AlertDialog.Builder(context)
        .setView(v)
        .setTitle(R.string.my_title)
        .setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick
        .setNegativeButton(android.R.string.cancel, null)
        .create();

dialog.setOnShowListener(new DialogInterface.OnShowListener() {

    @Override
    public void onShow(DialogInterface dialogInterface) {

        Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                // TODO Do something

                //Dismiss once everything is OK.
                dialog.dismiss();
            }
        });
    }
});
dialog.show();

7
เฮ้ดีกว่าไม่สายเลยฉันกำลังมองหาอย่างนั้นขอบคุณ +1 :) นี่เป็นวิธีที่ยอดเยี่ยมในการเพิ่มการตรวจสอบความถูกต้องในกล่องโต้ตอบของคุณโดยเฉพาะอย่างยิ่งเมื่อคุณมีคลาสตัวช่วยห่อเพื่อจัดการกับการแจ้งเตือน
Guillaume

11
ใช้งานไม่ได้ AlertDialog.Builder.setOnShowListener ไม่มีอยู่ developer.android.com/reference/android/app/…
Leandros

4
ด้วย API 8 ล่วงหน้าคุณสามารถโทร d.getButton (AlertDialog.BUTTON_POSITIVE); เนื่องจากเป็นวิธีสาธารณะ แต่คุณต้องเรียกมันว่า show (); ได้รับการเผยแพร่มิฉะนั้นคุณเพียงแค่ได้รับโมฆะจากมัน
Hurda

13
คุณสามารถทำให้เป็น tad Cleaner ได้โดยการตั้งค่า null เป็น OnClickListener ให้กับตัวสร้างไดอะล็อก (บันทึก "/ นี้จะว่างเปล่า" ฟัง) บันทึก
Steve Haley

1
ทำงานได้ดีกับ DialogFragments เมื่อมีการสร้าง AlertDialog ในเมธอด onCreateDialog (บันเดิลที่บันทึกไว้InstanceState)
Christian Lischnig

655

ต่อไปนี้เป็นวิธีแก้ไขปัญหาสำหรับกล่องโต้ตอบทุกประเภทรวมถึงโซลูชันสำหรับ AlertDialog.Builder ที่จะทำงานกับ API ทุกระดับ (ทำงานได้ต่ำกว่า API 8 ซึ่งคำตอบอื่น ๆ ที่นี่ไม่ได้) มีวิธีแก้ไขปัญหาสำหรับ AlertDialog โดยใช้ AlertDialog.Builder, DialogFragment และ DialogPreference

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

หมายเหตุ: คำอธิบายว่าการปิดกล่องโต้ตอบทำงานอย่างไรภายใต้ประทุนสำหรับคลาส Android พื้นฐานและทำไมเลือกแนวทางต่อไปนี้หลังจากตัวอย่างสำหรับผู้ที่ต้องการรายละเอียดเพิ่มเติม


AlertDialog.Builder - เปลี่ยนตัวจัดการปุ่มเริ่มต้นทันทีหลังจากแสดง ()

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Test for preventing dialog close");
builder.setPositiveButton("Test", 
        new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                //Do nothing here because we override this button later to change the close behaviour. 
                //However, we still need this because on older versions of Android unless we 
                //pass a handler the button doesn't get instantiated
            }
        });
final AlertDialog dialog = builder.create();
dialog.show();
//Overriding the handler immediately after show is probably a better approach than OnShowListener as described below
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
      {            
          @Override
          public void onClick(View v)
          {
              Boolean wantToCloseDialog = false;
              //Do stuff, possibly set wantToCloseDialog to true then...
              if(wantToCloseDialog)
                  dialog.dismiss();
              //else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
          }
      });

DialogFragment - แทนที่ onResume ()

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setMessage("Test for preventing dialog close");
    builder.setPositiveButton("Test", 
        new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                //Do nothing here because we override this button later to change the close behaviour. 
                //However, we still need this because on older versions of Android unless we 
                //pass a handler the button doesn't get instantiated
            }
        });
    return builder.create();
}

//onStart() is where dialog.show() is actually called on 
//the underlying dialog, so we have to do it there or 
//later in the lifecycle.
//Doing it in onResume() makes sure that even if there is a config change 
//environment that skips onStart then the dialog will still be functioning
//properly after a rotation.
@Override
public void onResume()
{
    super.onResume();    
    final AlertDialog d = (AlertDialog)getDialog();
    if(d != null)
    {
        Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
        positiveButton.setOnClickListener(new View.OnClickListener()
                {
                    @Override
                    public void onClick(View v)
                    {
                        Boolean wantToCloseDialog = false;
                        //Do stuff, possibly set wantToCloseDialog to true then...
                        if(wantToCloseDialog)
                            d.dismiss();
                        //else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
                    }
                });
    }
}

DialogPreference - แทนที่ showDialog ()

@Override
protected void onPrepareDialogBuilder(Builder builder)
{
    super.onPrepareDialogBuilder(builder);
    builder.setPositiveButton("Test", this);   //Set the button here so it gets created
}

@Override
protected void showDialog(Bundle state)
{       
    super.showDialog(state);    //Call show on default first so we can override the handlers

    final AlertDialog d = (AlertDialog) getDialog();
    d.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
            {            
                @Override
                public void onClick(View v)
                {
                    Boolean wantToCloseDialog = false;
                    //Do stuff, possibly set wantToCloseDialog to true then...
                    if(wantToCloseDialog)
                        d.dismiss();
                    //else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
                }
            });
}

คำอธิบายของวิธีการ:

การค้นหาผ่านซอร์สโค้ด Android การใช้งานเริ่มต้นของ AlertDialog นั้นทำได้โดยการลงทะเบียนตัวจัดการปุ่มทั่วไปกับปุ่มจริงทั้งหมดใน OnCreate () เมื่อคลิกปุ่มตัวจัดการปุ่มทั่วไปจะส่งต่อเหตุการณ์การคลิกไปยังตัวจัดการสิ่งที่คุณส่งผ่านใน setButton () จากนั้นการโทรจะยกเลิกการโต้ตอบ

หากคุณต้องการป้องกันไม่ให้กล่องโต้ตอบปิดลงเมื่อกดปุ่มใดปุ่มหนึ่งเหล่านี้คุณต้องแทนที่ตัวจัดการปุ่มทั่วไปสำหรับมุมมองที่แท้จริงของปุ่ม เนื่องจากมีการกำหนดไว้ใน OnCreate () คุณจะต้องแทนที่มันหลังจากเรียกใช้งาน OnCreate () เริ่มต้น OnCreate ถูกเรียกใช้ในกระบวนการแสดง () วิธีการ คุณสามารถสร้างคลาสไดอะล็อกที่กำหนดเองและลบล้าง OnCreate () เพื่อเรียกใช้ super.OnCreate () จากนั้นแทนที่ตัวจัดการปุ่ม แต่ถ้าคุณสร้างไดอะล็อกที่กำหนดเองคุณจะไม่ได้รับ Builder ฟรีซึ่งในกรณีนี้คือประเด็นอะไร ?

ดังนั้นในการใช้ไดอะล็อกวิธีที่ถูกออกแบบ แต่ด้วยการควบคุมเมื่อถูกยกเลิกวิธีการหนึ่งคือโทรไดอะล็อกแสดง () ก่อนจากนั้นรับการอ้างอิงถึงปุ่มโดยใช้ dialog.getButton () เพื่อแทนที่ตัวจัดการคลิก อีกวิธีคือใช้ setOnShowListener () และใช้การค้นหามุมมองปุ่มและแทนที่ handler ใน OnShowListener ความแตกต่างระหว่างการทำงานของทั้งสองคือ 'เกือบ' ไม่มีขึ้นอยู่กับสิ่งที่เธรดสร้างอินสแตนซ์โต้ตอบ เมื่อมองผ่านซอร์สโค้ด onShowListener จะถูกเรียกโดยข้อความที่โพสต์ไปยังตัวจัดการที่รันบนเธรดที่สร้างไดอะล็อกนั้น ดังนั้นเนื่องจาก OnShowListener ของคุณถูกเรียกโดยข้อความที่โพสต์บนคิวข้อความจึงเป็นไปได้ในทางเทคนิคว่าการเรียกผู้ฟังของคุณล่าช้าบางครั้งหลังจากการแสดงเสร็จ

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


12
นี่คือการใช้งานที่ง่ายที่สุดและทำงานได้อย่างสมบูรณ์แบบ ฉันใช้AlertDialog.Builder - เปลี่ยนตัวจัดการปุ่มเริ่มต้นทันทีหลังจากแสดง ()และมันใช้งานได้อย่างมีเสน่ห์
เพิ่ม

1
@ sogger เพื่อนฉันแก้ไขคำตอบที่น่าอัศจรรย์ทั้งหมดของคุณอย่างสิ้นเชิงเพราะในส่วนที่ 1 คุณเลิกทำ (); แทนฉันเชื่อ dialog.dismiss (); ขอบคุณมากสำหรับคำตอบที่ยอดเยี่ยม!
Fattie

มีวิธีใดบ้างที่จะป้องกันการปิดProgressDialogเมื่อมีการคลิกที่ปุ่มนี้?
Joshua Pinter

1
Holy cow, ยิ่งฉันรู้เกี่ยวกับ Android มากเท่าไหร่ฉันก็รู้สึกเบื่อหน่ายมากขึ้น ... ทั้งหมดนี้เพียงเพื่อให้ไดอะล็อกง่าย ๆ ทำงานอย่างถูกต้อง มันต้องใช้เวลาหลายชั่วโมงกว่าจะหาวิธีแสดงไดอะล็อก
SpaceMonkey

1
@harsh_v อัปเดตคำตอบเพื่อใช้ onResume () สำหรับคนต่อไปขอบคุณ!
Sogger

37

ทางเลือกอื่น

ฉันต้องการนำเสนอคำตอบอื่นจากมุมมองของ UX

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

คำตอบอื่น ๆ ที่นี่ให้เทคนิคมากมายสำหรับการเอาชนะการคลิกปุ่มบวก หากเป็นสิ่งสำคัญที่ต้องทำ Android จะไม่ทำวิธีที่สะดวกในการทำหรือไม่? พวกเขาไม่ได้

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

ป้อนคำอธิบายรูปภาพที่นี่

วิธีปิดการใช้งานปุ่มบวก

ดูเอกสาร Android สำหรับการสร้างรูปแบบโต้ตอบที่กำหนดเอง มันขอแนะนำให้คุณวางของคุณภายในAlertDialog DialogFragmentจากนั้นสิ่งที่คุณต้องทำคือตั้งค่าฟังบนองค์ประกอบเลย์เอาต์ให้รู้ว่าเมื่อใดที่จะเปิดหรือปิดใช้งานปุ่มบวก

  • หากกล่องโต้ตอบแบบกำหนดเองของคุณมีปุ่มตัวเลือกให้ใช้RadioGroupOnCheckedChangeListener RadioGroup.OnCheckedChangeListener
  • หากกล่องโต้ตอบแบบกำหนดเองของคุณมีช่องทำเครื่องหมายให้ใช้CompoundButtonOnCheckedChangeListener CompoundButton.OnCheckedChangeListener
  • ถ้าโต้ตอบกำหนดเองของคุณมีEditTextแล้วใช้TextWatcher

ปุ่มบวกสามารถปิดการใช้งานเช่นนี้:

AlertDialog dialog = (AlertDialog) getDialog();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);

นี่คือการทำงานทั้งหมดDialogFragmentกับปุ่มบวกปิดการใช้งานเช่นอาจจะใช้ในภาพด้านบน

import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;

public class MyDialogFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        // inflate the custom dialog layout
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.my_dialog_layout, null);

        // add a listener to the radio buttons
        RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.radio_group);
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                // enable the positive button after a choice has been made
                AlertDialog dialog = (AlertDialog) getDialog();
                dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
            }
        });

        // build the alert dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setView(view)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        // TODO: use an interface to pass the user choice back to the activity
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        MyDialogFragment.this.getDialog().cancel();
                    }
                });
        return builder.create();
    }

    @Override
    public void onResume() {
        super.onResume();

        // disable positive button by default
        AlertDialog dialog = (AlertDialog) getDialog();
        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
    }
}

กล่องโต้ตอบที่กำหนดเองสามารถเรียกใช้จากกิจกรรมเช่นนี้:

MyDialogFragment dialog = new MyDialogFragment();
dialog.show(getFragmentManager(), "MyTag");

หมายเหตุ

  • เพื่อความกะทัดรัดฉันได้ข้ามส่วนติดต่อสื่อสารเพื่อส่งผ่านข้อมูลตัวเลือกของผู้ใช้กลับไปที่กิจกรรม เอกสารแสดงให้เห็นว่าวิธีนี้จะทำแม้ว่า
  • ปุ่มยังอยู่nullในดังนั้นฉันปิดการใช้งานในonCreateDialog onResumeสิ่งนี้มีผลที่ไม่พึงประสงค์จากการปิดใช้งานอีกครั้งหากผู้ใช้สลับไปที่แอพอื่นแล้วกลับมาโดยไม่ยกเลิกการโต้ตอบ สิ่งนี้สามารถแก้ไขได้โดยยกเลิกการเลือกตัวเลือกของผู้ใช้หรือโดยการโทรRunnableจากonCreateDialogเพื่อปิดการใช้งานปุ่มในการวนรอบถัดไป

    view.post(new Runnable() {
        @Override
        public void run() {
            AlertDialog dialog = (AlertDialog) getDialog();
            dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
        }
    });

ที่เกี่ยวข้อง


33

ฉันได้เขียนคลาสแบบง่าย ๆ (เป็น AlertDialogBuilder) ที่คุณสามารถใช้เพื่อปิดใช้งานคุณสมบัติการปิดอัตโนมัติเมื่อกดปุ่มของกล่องโต้ตอบ

มันเข้ากันได้กับ Android 1.6 ดังนั้นมันจึงไม่ใช้ OnShowListener (ซึ่งมีเฉพาะ API> = 8)

ดังนั้นแทนที่จะใช้ AlertDialog.Builder คุณสามารถใช้ CustomAlertDialogBuilder นี้ ส่วนที่สำคัญที่สุดคือคุณไม่ควรเรียกcreate ()แต่ใช้วิธีshow ()เท่านั้น ฉันได้เพิ่มวิธีการเช่นsetCanceledOnTouchOutside ()และsetOnDismissListenerเพื่อให้คุณยังคงสามารถตั้งค่าเหล่านั้นได้โดยตรงบนตัวสร้าง

ฉันทดสอบกับ Android 1.6, 2.x, 3.x และ 4.x ดังนั้นมันน่าจะใช้ได้ดี หากคุณพบปัญหากรุณาแสดงความคิดเห็นที่นี่

package com.droidahead.lib.utils;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
import android.view.View.OnClickListener;

public class CustomAlertDialogBuilder extends AlertDialog.Builder {
    /**
     * Click listeners
     */
    private DialogInterface.OnClickListener mPositiveButtonListener = null;
    private DialogInterface.OnClickListener mNegativeButtonListener = null;
    private DialogInterface.OnClickListener mNeutralButtonListener = null;

    /**
     * Buttons text
     */
    private CharSequence mPositiveButtonText = null;
    private CharSequence mNegativeButtonText = null;
    private CharSequence mNeutralButtonText = null;

    private DialogInterface.OnDismissListener mOnDismissListener = null;

    private Boolean mCancelOnTouchOutside = null;

    public CustomAlertDialogBuilder(Context context) {
        super(context);
    }

    public CustomAlertDialogBuilder setOnDismissListener (DialogInterface.OnDismissListener listener) {
        mOnDismissListener = listener;
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) {
        mNegativeButtonListener = listener;
        mNegativeButtonText = text;
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) {
        mNeutralButtonListener = listener;
        mNeutralButtonText = text;
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) {
        mPositiveButtonListener = listener;
        mPositiveButtonText = text;
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setNegativeButton(int textId, DialogInterface.OnClickListener listener) {
        setNegativeButton(getContext().getString(textId), listener);
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setNeutralButton(int textId, DialogInterface.OnClickListener listener) {
        setNeutralButton(getContext().getString(textId), listener);
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setPositiveButton(int textId, DialogInterface.OnClickListener listener) {
        setPositiveButton(getContext().getString(textId), listener);
        return this;
    }

    public CustomAlertDialogBuilder setCanceledOnTouchOutside (boolean cancelOnTouchOutside) {
        mCancelOnTouchOutside = cancelOnTouchOutside;
        return this;
    }



    @Override
    public AlertDialog create() {
        throw new UnsupportedOperationException("CustomAlertDialogBuilder.create(): use show() instead..");
    }

    @Override
    public AlertDialog show() {
        final AlertDialog alertDialog = super.create();

        DialogInterface.OnClickListener emptyOnClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) { }
        };


        // Enable buttons (needed for Android 1.6) - otherwise later getButton() returns null
        if (mPositiveButtonText != null) {
            alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, mPositiveButtonText, emptyOnClickListener);
        }

        if (mNegativeButtonText != null) {
            alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, mNegativeButtonText, emptyOnClickListener);
        }

        if (mNeutralButtonText != null) {
            alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, mNeutralButtonText, emptyOnClickListener);
        }

        // Set OnDismissListener if available
        if (mOnDismissListener != null) {
            alertDialog.setOnDismissListener(mOnDismissListener);
        }

        if (mCancelOnTouchOutside != null) {
            alertDialog.setCanceledOnTouchOutside(mCancelOnTouchOutside);
        }

        alertDialog.show();

        // Set the OnClickListener directly on the Button object, avoiding the auto-dismiss feature
        // IMPORTANT: this must be after alert.show(), otherwise the button doesn't exist..
        // If the listeners are null don't do anything so that they will still dismiss the dialog when clicked
        if (mPositiveButtonListener != null) {
            alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    mPositiveButtonListener.onClick(alertDialog, AlertDialog.BUTTON_POSITIVE);
                }
            });
        }

        if (mNegativeButtonListener != null) {
            alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    mNegativeButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEGATIVE);
                }
            });
        }

        if (mNeutralButtonListener != null) {
            alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    mNeutralButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEUTRAL);
                }
            });
        }

        return alertDialog;
    }   
}

แก้ไขนี่คือตัวอย่างเล็ก ๆ เกี่ยวกับวิธีการใช้ CustomAlertDialogBuilder:

// Create the CustomAlertDialogBuilder
CustomAlertDialogBuilder dialogBuilder = new CustomAlertDialogBuilder(context);

// Set the usual data, as you would do with AlertDialog.Builder
dialogBuilder.setIcon(R.drawable.icon);
dialogBuilder.setTitle("Dialog title");
dialogBuilder.setMessage("Some text..");

// Set your buttons OnClickListeners
dialogBuilder.setPositiveButton ("Button 1", new DialogInterface.OnClickListener() {
    public void onClick (DialogInterface dialog, int which) {
        // Do something...

        // Dialog will not dismiss when the button is clicked
        // call dialog.dismiss() to actually dismiss it.
    }
});

// By passing null as the OnClickListener the dialog will dismiss when the button is clicked.               
dialogBuilder.setNegativeButton ("Close", null);

// Set the OnDismissListener (if you need it)       
dialogBuilder.setOnDismissListener(new DialogInterface.OnDismissListener() {
    public void onDismiss(DialogInterface dialog) {
        // dialog was just dismissed..
    }
});

// (optional) set whether to dismiss dialog when touching outside
dialogBuilder.setCanceledOnTouchOutside(false);

// Show the dialog
dialogBuilder.show();

ไชโย

Yuvi


ดี แต่ไม่ได้ผลสำหรับฉัน ไดอะล็อกถูกไล่ออก
Leandros

อืมมฟังดูแปลก ๆ ฉันใช้สิ่งนั้นในแอปของฉันและมีเพียงปุ่มเดียวเท่านั้นที่ฉันโทรหา dialog.dismiss () อย่างชัดเจนจะยกเลิกกล่องโต้ตอบ คุณกำลังทดสอบเวอร์ชั่น Android ในเวอร์ชันใด? คุณสามารถแสดงรหัสที่คุณใช้ CustomAlertDialogBuilder ได้หรือไม่?
YuviDroid

ฉันคิดว่ามันจะเกิดขึ้นเพราะเหตุนี้: (โทร dialog.show () หลังจาก OnClickListener) pastebin.com/uLnSu5v7ถ้าฉันคลิก positiveButton พวกเขาได้รับการยอมรับถ้าบูลเป็นความจริง ...
Leandros

ฉันไม่ได้ทดสอบโดยใช้ Activity.onCreateDialog () อาจเป็นไปไม่ได้ที่จะทำเช่นนั้น ฉันจะแก้ไข 'คำตอบ' เพื่อรวมตัวอย่างเล็ก ๆ เกี่ยวกับวิธีใช้งาน
YuviDroid

4
สิ่งนี้ใช้ได้กับฉันด้วยการแก้ไขปัจจุบัน! อย่างไรก็ตาม: หนึ่งข้อแม้เพิ่มเติม Builder.getContext () ใช้ได้กับ API 11+ เท่านั้น เพิ่มเขตข้อมูลContext mContextและตั้งค่าในตัวสร้างแทน
Oleg Vaskevich

28

นี่คือสิ่งที่คุณกำลังใช้DialogFragmentซึ่งเป็นวิธีที่แนะนำในการจัดการกับกล่องโต้ตอบ

สิ่งที่เกิดขึ้นกับsetButton()วิธีการของ AlertDialog (และฉันคิดว่าเหมือนกันกับAlertDialogBuilder's setPositiveButton()และsetNegativeButton()) คือปุ่มที่คุณตั้งค่า (เช่นAlertDialog.BUTTON_POSITIVE) ด้วยจริง ๆ แล้วมันจะทริกเกอร์ TWO ที่แตกต่างกันOnClickListenerวัตถุเมื่อกด

ตัวแรกDialogInterface.OnClickListenerซึ่งเป็นพารามิเตอร์ไปsetButton(), และsetPositiveButton()setNegativeButton()

อีกอันคือViewOnClickListenerซึ่งจะถูกตั้งค่าให้ปิดการใช้งานของคุณโดยอัตโนมัติAlertDialogเมื่อมีการกดปุ่มใดปุ่มหนึ่งและตั้งค่าด้วยAlertDialogตัวเอง

สิ่งที่คุณสามารถทำได้คือการใช้setButton()กับnullเป็นการสร้างปุ่มและแล้วโทรที่กำหนดเองวิธีการดำเนินการภายในของคุณDialogInterface.OnClickListener View.OnClickListenerตัวอย่างเช่น,

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    AlertDialog alertDialog = new AlertDialog(getActivity());
    // set more items...
    alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", null);

    return alertDialog;
}

จากนั้นคุณอาจแทนที่ค่าเริ่มต้นAlertDialogของปุ่ม ' View.OnClickListener(ซึ่งอาจจะยกเลิกการโต้ตอบ) ในDialogFragment's onResume()วิธีการ:

@Override
public void onResume()
{
    super.onResume();
    AlertDialog alertDialog = (AlertDialog) getDialog();
    Button okButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
    okButton.setOnClickListener(new View.OnClickListener() { 
        @Override
        public void onClick(View v)
        {
            performOkButtonAction();
        }
    });
}

private void performOkButtonAction() {
    // Do your stuff here
}

คุณจะต้องตั้งค่านี้ในonResume()วิธีการเพราะgetButton()จะกลับมาnullจนกว่าจะมีการแสดงกล่องโต้ตอบ!

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


21

แรงบันดาลใจจากคำตอบของทอมฉันเชื่อว่าความคิดที่นี่คือ:

  • ตั้งค่าonClickListenerระหว่างการสร้างไดอะล็อกเป็นnull
  • จากนั้นตั้งค่า a onClickListenerหลังจากไดอะล็อกถูกแสดง

คุณสามารถแทนที่onShowListenerทอมที่ชอบได้ หรือคุณสามารถ

  1. รับปุ่มหลังจากโทรไปยัง AlertDialog show()
  2. ตั้งปุ่ม ' onClickListenerดังต่อไปนี้ (ฉันคิดว่าอ่านง่ายขึ้นเล็กน้อย)

รหัส:

AlertDialog.Builder builder = new AlertDialog.Builder(context);
// ...
final AlertDialog dialog = builder.create();
dialog.show();
// now you can override the default onClickListener
Button b = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
b.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Log.i(TAG, "ok button is clicked");
        handleClick(dialog);
    }
});

8

สำหรับ API 8 ก่อนหน้าฉันแก้ไขปัญหาโดยใช้แฟล็กบูลีนผู้ฟังที่ถูกไล่ออกและการเรียกใช้ dialog.show อีกครั้งหากในกรณีที่เนื้อหาของ editText ไม่ถูกต้อง แบบนี้:

case ADD_CLIENT:
        LayoutInflater factoryClient = LayoutInflater.from(this);
        final View EntryViewClient = factoryClient.inflate(
                R.layout.alert_dialog_add_client, null);

        EditText ClientText = (EditText) EntryViewClient
                .findViewById(R.id.client_edit);

        AlertDialog.Builder builderClient = new AlertDialog.Builder(this);
        builderClient
                .setTitle(R.string.alert_dialog_client)
                .setCancelable(false)
                .setView(EntryViewClient)
                .setPositiveButton("Save",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                    int whichButton) {
                                EditText newClient = (EditText) EntryViewClient
                                        .findViewById(R.id.client_edit);
                                String newClientString = newClient
                                        .getText().toString();
                                if (checkForEmptyFields(newClientString)) {
                                    //If field is empty show toast and set error flag to true;
                                    Toast.makeText(getApplicationContext(),
                                            "Fields cant be empty",
                                            Toast.LENGTH_SHORT).show();
                                    add_client_error = true;
                                } else {
                                    //Here save the info and set the error flag to false
                                    add_client_error = false;
                                }
                            }
                        })
                .setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                    int id) {
                                add_client_error = false;
                                dialog.cancel();
                            }
                        });
        final AlertDialog alertClient = builderClient.create();
        alertClient.show();

        alertClient
                .setOnDismissListener(new DialogInterface.OnDismissListener() {

                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        //If the error flag was set to true then show the dialog again
                        if (add_client_error == true) {
                            alertClient.show();
                        } else {
                            return;
                        }

                    }
                });
        return true;

สิ่งแปลกประหลาดบนไม่รับเรียกฉันเป็น api ระดับ 21
duckduckgo

7

คำตอบที่ลิงค์นี้เป็นคำตอบที่ง่ายและสามารถใช้งานได้กับ API 3 ซึ่งเป็นวิธีที่คุ้นเคยกับโซลูชันของ Tom Bollwitt แต่ไม่ต้องใช้ OnShowListener ที่เข้ากันได้น้อย

ใช่คุณสามารถ. คุณจำเป็นต้อง:

  1. สร้างกล่องโต้ตอบด้วย DialogBuilder
  2. แสดง () กล่องโต้ตอบ
  3. ค้นหาปุ่มในกล่องโต้ตอบที่แสดงและแทนที่ onClickListener

ฉันทำการดัดแปลงเล็กน้อยกับรหัสของ Kamen ตั้งแต่ฉันขยาย EditTextPreference

@Override
protected void showDialog(Bundle state) {
  super.showDialog(state);

  class mocl implements OnClickListener{
    private final AlertDialog dialog;
    public mocl(AlertDialog dialog) {
          this.dialog = dialog;
      }
    @Override
    public void onClick(View v) {

        //checks if EditText is empty, and if so tells the user via Toast
        //otherwise it closes dialog and calls the EditTextPreference's onClick
        //method to let it know that the button has been pressed

        if (!IntPreference.this.getEditText().getText().toString().equals("")){
        dialog.dismiss();
        IntPreference.this.onClick(dialog,DialogInterface.BUTTON_POSITIVE);
        }
        else {
            Toast t = Toast.makeText(getContext(), "Enter a number!", Toast.LENGTH_SHORT);
            t.show();
        }

    }
  }

  AlertDialog d = (AlertDialog) getDialog();
  Button b = d.getButton(DialogInterface.BUTTON_POSITIVE);
  b.setOnClickListener(new mocl((d)));
}

สนุกดังกล่าว!


4

รหัสนี้จะทำงานสำหรับคุณเพราะฉันมีปัญหาที่คล้ายกันและสิ่งนี้ได้ผลสำหรับฉัน :)

1- วิธีการแทนที่ Onstart () ในชั้นโต้ตอบส่วนของคุณ

@Override
public void onStart() {
    super.onStart();
    final AlertDialog D = (AlertDialog) getDialog();
    if (D != null) {
        Button positive = (Button) D.getButton(Dialog.BUTTON_POSITIVE);
        positive.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if (edittext.equals("")) {
   Toast.makeText(getActivity(), "EditText empty",Toast.LENGTH_SHORT).show();
                } else {
                D.dismiss(); //dissmiss dialog
                }
            }
        });
    }
}

3

สำหรับ ProgressDialogs

ในการป้องกันไม่ให้ไดอะล็อกถูกไล่ออกโดยอัตโนมัติคุณต้องตั้งค่าOnClickListenerหลังจากProgressDialogแสดงดังนี้:

connectingDialog = new ProgressDialog(this);

connectingDialog.setCancelable(false);
connectingDialog.setCanceledOnTouchOutside(false);

// Create the button but set the listener to a null object.
connectingDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", 
        (DialogInterface.OnClickListener) null )

// Show the dialog so we can then get the button from the view.
connectingDialog.show();

// Get the button from the view.
Button dialogButton = connectingDialog.getButton( DialogInterface.BUTTON_NEGATIVE);

// Set the onClickListener here, in the view.
dialogButton.setOnClickListener( new View.OnClickListener() {

    @Override
    public void onClick ( View v ) {

        // Dialog will not get dismissed until you call dismiss() explicitly.

    }

});

3
public class ComentarDialog extends DialogFragment{
private EditText comentario;

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    LayoutInflater inflater = LayoutInflater.from(getActivity());
    View v = inflater.inflate(R.layout.dialog_comentar, null);
    comentario = (EditText)v.findViewById(R.id.etxt_comentar_dialog);

    builder.setTitle("Comentar")
           .setView(v)
           .setPositiveButton("OK", null)
           .setNegativeButton("CANCELAR", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {

               }
           });

    return builder.create();
}

@Override
public void onStart() {
    super.onStart();

    //Obtenemos el AlertDialog
    AlertDialog dialog = (AlertDialog)getDialog();

    dialog.setCanceledOnTouchOutside(false);
    dialog.setCancelable(false);//Al presionar atras no desaparece

    //Implementamos el listener del boton OK para mostrar el toast
    dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(TextUtils.isEmpty(comentario.getText())){
               Toast.makeText(getActivity(), "Ingrese un comentario", Toast.LENGTH_SHORT).show();
               return;
            }
            else{
                ((AlertDialog)getDialog()).dismiss();
            }
        }
    });

    //Personalizamos
    Resources res = getResources();

    //Buttons
    Button positive_button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
    positive_button.setBackground(res.getDrawable(R.drawable.btn_selector_dialog));

    Button negative_button =  dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
    negative_button.setBackground(res.getDrawable(R.drawable.btn_selector_dialog));

    int color = Color.parseColor("#304f5a");

    //Title
    int titleId = res.getIdentifier("alertTitle", "id", "android");
    View title = dialog.findViewById(titleId);
    if (title != null) {
        ((TextView) title).setTextColor(color);
    }

    //Title divider
    int titleDividerId = res.getIdentifier("titleDivider", "id", "android");
    View titleDivider = dialog.findViewById(titleDividerId);
    if (titleDivider != null) {
        titleDivider.setBackgroundColor(res.getColor(R.color.list_menu_divider));
    }
}
}

3

คุณสามารถเพิ่ม builder.show (); หลังจากข้อความตรวจสอบก่อนที่จะกลับมา;

แบบนี้

    public void login()
{
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setView(R.layout.login_layout);
    builder.setTitle("Login");



    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int id)
        {
            dialog.cancel();
        }
    });// put the negative button before the positive button, so it will appear

    builder.setPositiveButton("Ok", new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int id)
        {
            Dialog d = (Dialog) dialog;
            final EditText etUserName = (EditText) d.findViewById(R.id.etLoginName);
            final EditText etPassword = (EditText) d.findViewById(R.id.etLoginPassword);
            String userName = etUserName.getText().toString().trim();
            String password = etPassword.getText().toString().trim();

            if (userName.isEmpty() || password.isEmpty())
            {

                Toast.makeText(getApplicationContext(),
                        "Please Fill all fields", Toast.LENGTH_SHORT).show();
                builder.show();// here after validation message before retrun
                               //  it will reopen the dialog
                              // till the user enter the right condition
                return;
            }

            user = Manager.get(getApplicationContext()).getUserByName(userName);

            if (user == null)
            {
                Toast.makeText(getApplicationContext(),
                        "Error ethier username or password are wrong", Toast.LENGTH_SHORT).show();
                builder.show();
                return;
            }
            if (password.equals(user.getPassword()))
            {
                etPassword.setText("");
                etUserName.setText("");
                setLogged(1);
                setLoggedId(user.getUserId());
                Toast.makeText(getApplicationContext(),
                        "Successfully logged in", Toast.LENGTH_SHORT).show();
               dialog.dismiss();// if every thing is ok then dismiss the dialog
            }
            else
            {
                Toast.makeText(getApplicationContext(),
                        "Error ethier username or password are wrong", Toast.LENGTH_SHORT).show();
                builder.show();
                return;
            }

        }
    });

    builder.show();

}

3

เพื่อป้องกันไม่ให้กล่องโต้ตอบปิดลงเมื่อคลิกและควรปิดเฉพาะเมื่ออินเทอร์เน็ตพร้อมใช้งาน

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

นี่คือรหัสของฉัน:

AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this); builder.setTitle("Internet Not Connected");
    if(ifConnected()){

        Toast.makeText(this, "Connected or not", Toast.LENGTH_LONG).show();
    }
    else{
        builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
               if(!ifConnected())
               {
                   builder.show();
               }
            }
        }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                finish();
            }
        });
        builder.show();

    }

และนี่คือรหัสเครื่องมือจัดการการเชื่อมต่อของฉัน:

 private boolean ifConnected()
{
    ConnectivityManager connectivityManager= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
   return networkInfo!=null && networkInfo.isConnected();
}

นี่ฉลาด แต่ฉันได้รับข้อความแสดงข้อผิดพลาดนี้:The specified child already has a parent. You must call removeView() on the child's parent first
Dan Chaltiel

2

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


1

ใช้เค้าโครงที่กำหนดเองสำหรับคุณDialogFragmentและเพิ่มLinearLayoutเนื้อหาภายใต้ของคุณซึ่งสามารถจัดสไตล์เป็นแบบไร้ขอบเพื่อให้เข้ากับการออกแบบวัสดุของ Google จากนั้นหาปุ่มที่สร้างขึ้นใหม่และแทนที่ปุ่มเหล่านั้นOnClickListenerนั้น

ตัวอย่าง:

public class AddTopicFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        // Get the layout inflater
        LayoutInflater inflater = getActivity().getLayoutInflater();
        final View dialogView = inflater.inflate(R.layout.dialog_add_topic, null);

        Button saveTopicDialogButton = (Button) dialogView.findViewById(R.id.saveTopicDialogButton);
        Button cancelSaveTopicDialogButton = (Button) dialogView.findViewById(R.id.cancelSaveTopicDialogButton);

        final AppCompatEditText addTopicNameET = (AppCompatEditText) dialogView.findViewById(R.id.addTopicNameET);
        final AppCompatEditText addTopicCreatedByET = (AppCompatEditText) dialogView.findViewById(R.id.addTopicCreatedByET);

        saveTopicDialogButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // validate inputs
                if(addTopicNameET.getText().toString().trim().isEmpty()){
                    addTopicNameET.setError("Topic name can't be empty");
                    addTopicNameET.requestFocus();
                }else if(addTopicCreatedByET.getText().toString().trim().isEmpty()){
                    addTopicCreatedByET.setError("Topic created by can't be empty");
                    addTopicCreatedByET.requestFocus();
                }else {
                    // save topic to database
                    Topic topic = new Topic();
                    topic.name = addTopicNameET.getText().toString().trim();
                    topic.createdBy = addTopicCreatedByET.getText().toString().trim();
                    topic.createdDate = new Date().getTime();
                    topic.save();
                    AddTopicFragment.this.dismiss();
                }
            }
        });

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

        // Inflate and set the layout for the dialog
        // Pass null as the parent view because its going in the dialog layout
        builder.setView(dialogView)
               .setMessage(getString(R.string.add_topic_message));

        return builder.create();
    }

}

dialog_add_topic.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:errorEnabled="true">

        <android.support.v7.widget.AppCompatEditText
            android:id="@+id/addTopicNameET"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Topic Name"
            android:inputType="textPersonName"
            android:maxLines="1" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:errorEnabled="true">

        <android.support.v7.widget.AppCompatEditText
            android:id="@+id/addTopicCreatedByET"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Created By"
            android:inputType="textPersonName"
            android:maxLines="1" />

    </android.support.design.widget.TextInputLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:text="@string/cancel"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cancelSaveTopicDialogButton"
            style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog" />

        <Button
            android:text="@string/save"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/saveTopicDialogButton"
            style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog" />

    </LinearLayout>


</LinearLayout>

นี่คือผลลัพธ์สุดท้าย


0

มันสามารถสร้างด้วยวิธีที่ง่ายที่สุด:

กล่องโต้ตอบแจ้งเตือนพร้อมมุมมองที่กำหนดเองและปุ่มสองปุ่ม (บวก & ลบ)

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setTitle(getString(R.string.select_period));
builder.setPositiveButton(getString(R.string.ok), null);

 builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {

    // Click of Cancel Button

   }
 });

  LayoutInflater li = LayoutInflater.from(getActivity());
  View promptsView = li.inflate(R.layout.dialog_date_picker, null, false);
  builder.setView(promptsView);

  DatePicker startDatePicker = (DatePicker)promptsView.findViewById(R.id.startDatePicker);
  DatePicker endDatePicker = (DatePicker)promptsView.findViewById(R.id.endDatePicker);

  final AlertDialog alertDialog = builder.create();
  alertDialog.show();

  Button theButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
  theButton.setOnClickListener(new CustomListener(alertDialog, startDatePicker, endDatePicker));

CustomClickListerของปุ่มบวกของการเตือน Dailog :

private class CustomListener implements View.OnClickListener {
        private final Dialog dialog;
        private DatePicker mStartDp, mEndDp;
    public CustomListener(Dialog dialog, DatePicker dS, DatePicker dE) {
        this.dialog = dialog;
        mStartDp = dS;
        mEndDp = dE;
    }

    @Override
    public void onClick(View v) {

        int day1  = mStartDp.getDayOfMonth();
        int month1= mStartDp.getMonth();
        int year1 = mStartDp.getYear();
        Calendar cal1 = Calendar.getInstance();
        cal1.set(Calendar.YEAR, year1);
        cal1.set(Calendar.MONTH, month1);
        cal1.set(Calendar.DAY_OF_MONTH, day1);


        int day2  = mEndDp.getDayOfMonth();
        int month2= mEndDp.getMonth();
        int year2 = mEndDp.getYear();
        Calendar cal2 = Calendar.getInstance();
        cal2.set(Calendar.YEAR, year2);
        cal2.set(Calendar.MONTH, month2);
        cal2.set(Calendar.DAY_OF_MONTH, day2);

        if(cal2.getTimeInMillis()>=cal1.getTimeInMillis()){
            dialog.dismiss();
            Log.i("Dialog", "Dismiss");
            // Condition is satisfied so do dialog dismiss
            }else {
            Log.i("Dialog", "Do not Dismiss");
            // Condition is not satisfied so do not dialog dismiss
        }

    }
}

เสร็จสิ้น


-1

นี่อาจเป็นคำตอบที่ล่าช้ามาก แต่การใช้ setCancelable จะเป็นการหลอกลวง

alertDial.setCancelable(false);

10
จากเอกสาร: "ตั้งค่าว่าจะให้กล่องโต้ตอบนี้สามารถยกเลิกได้ด้วยปุ่ม BACK" สิ่งนี้ไม่เกี่ยวข้องกับปุ่มบวกที่จะยกเลิกไดอะล็อก ..
clauziere

3
ใช้งานไม่ได้สำหรับฉัน แต่ยังคงยกเลิกเมื่อคลิกปุ่มบวก
Hugo

1
สิ่งนี้ไม่เกี่ยวกับ OP
MatPag

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