Berikut adalah beberapa solusi untuk semua jenis dialog termasuk solusi untuk AlertDialog.Builder yang akan bekerja pada semua level API (bekerja di bawah API 8, yang jawaban lain di sini tidak). Ada solusi untuk AlertDialogs menggunakan AlertDialog.Builder, DialogFragment, dan DialogPreference.
Di bawah ini adalah contoh kode yang menunjukkan cara mengganti penangan tombol umum yang umum dan mencegah dialog menutup untuk bentuk dialog yang berbeda ini. Semua contoh menunjukkan bagaimana mencegah tombol positif menutup dialog.
Catatan: Deskripsi tentang cara kerja dialog penutup di bawah tenda untuk kelas android dasar dan mengapa pendekatan berikut dipilih mengikuti contoh-contoh, bagi mereka yang ingin lebih detail
AlertDialog.Builder - Ubah penangan tombol default segera setelah show ()
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 - override 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 - ganti 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.
}
});
}
Penjelasan pendekatan:
Melihat melalui kode sumber Android, implementasi default AlertDialog bekerja dengan mendaftarkan pengendali tombol umum ke semua tombol aktual di OnCreate (). Ketika sebuah tombol diklik, handler tombol umum meneruskan acara klik ke handler apa pun yang Anda lewati di setButton () lalu panggilan mengabaikan dialog.
Jika Anda ingin mencegah kotak dialog menutup ketika salah satu tombol ini ditekan, Anda harus mengganti penangan tombol umum untuk tampilan tombol yang sebenarnya. Karena ditugaskan di OnCreate (), Anda harus menggantinya setelah implementasi OnCreate () default dipanggil. OnCreate dipanggil dalam proses metode show (). Anda bisa membuat kelas Dialog khusus dan menimpa OnCreate () untuk memanggil super.OnCreate () kemudian menimpa penangan tombol, tetapi jika Anda membuat dialog kustom Anda tidak mendapatkan Builder gratis, dalam hal apa gunanya titik ?
Jadi, dalam menggunakan dialog cara itu dirancang tetapi dengan mengendalikan ketika itu diberhentikan, salah satu pendekatan adalah untuk memanggil dialog. Tunjukkan () terlebih dahulu, kemudian dapatkan referensi ke tombol menggunakan dialog.getButton () untuk mengganti penangan klik. Pendekatan lain adalah dengan menggunakan setOnShowListener () dan mengimplementasikan menemukan tampilan tombol dan mengganti handler di OnShowListener. Perbedaan fungsional antara keduanya adalah 'hampir' nill, tergantung pada utas yang awalnya membuat instance dialog. Melihat melalui kode sumber, onShowListener dipanggil oleh pesan yang diposting ke penangan yang berjalan di utas yang membuat dialog itu. Jadi, karena OnShowListener Anda dipanggil oleh pesan yang diposting di antrian pesan, secara teknis dimungkinkan bahwa panggilan pendengar Anda tertunda beberapa saat setelah pertunjukan selesai.
Oleh karena itu, saya percaya pendekatan teraman adalah yang pertama: memanggil show.Dialog (), lalu segera di jalur eksekusi yang sama, ganti penangan tombol. Karena kode Anda yang memanggil show () akan beroperasi pada utas GUI utama, itu berarti kode apa pun yang Anda ikuti tampilkan () dengan akan dieksekusi sebelum kode lain pada utas itu, sedangkan waktu metode OnShowListener berada di bawah kendali antrian pesan.