AlertDialog.Builder için tüm API seviyelerinde çalışacak bir çözüm de dahil olmak üzere tüm iletişim kutuları için bazı çözümler (burada diğer cevabın olmadığı API 8'in altında çalışır). AlertDialog.Builder, DialogFragment ve DialogPreference kullanan AlertDialog'lar için çözümler vardır.
Aşağıda, varsayılan ortak düğme işleyicisini geçersiz kılmayı ve iletişim kutusunun bu farklı iletişim kutuları için kapanmasını önleyen kod örnekleri verilmiştir. Tüm örnekler, pozitif düğmenin iletişim kutusunu kapatmasının nasıl önleneceğini gösterir.
Not: Temel android sınıfları için iletişim kutusunun kaputunun altında nasıl çalıştığının ve aşağıdaki yaklaşımların neden seçildiğinin açıklaması, daha fazla ayrıntı isteyenler için aşağıdaki örneklerden sonra verilmiştir.
AlertDialog.Builder - Gösteriden hemen sonra varsayılan düğme işleyicisini değiştir ()
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 () geçersiz kıl
@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 () 'u geçersiz kıl
@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.
}
});
}
Yaklaşımların açıklaması:
Android kaynak koduna bakıldığında, AlertDialog varsayılan uygulaması, OnCreate () içindeki tüm gerçek düğmelere ortak bir düğme işleyicisi kaydederek çalışır. Bir düğmeye tıklandığında ortak düğme işleyici, click olayını setButton () öğesine ilettiğiniz işleyiciye iletir ve ardından çağrılar iletişim kutusunu kapatır.
Bu düğmelerden birine basıldığında bir iletişim kutusunun kapanmasını önlemek istiyorsanız, düğmenin gerçek görünümü için ortak düğme işleyicisini değiştirmeniz gerekir. OnCreate () içinde atandığından, varsayılan OnCreate () uygulaması çağrıldıktan sonra bunu değiştirmeniz gerekir. Show () yönteminin işleminde OnCreate çağrılır. Özel bir Dialog sınıfı oluşturabilir ve super.OnCreate () yöntemini çağırmak için OnCreate () yöntemini geçersiz kılabilir, ardından düğme işleyicilerini geçersiz kılabilirsiniz, ancak özel bir iletişim kutusu oluşturursanız Oluşturucuyu ücretsiz olarak alamazsınız; ?
Bu nedenle, bir iletişim kutusunu tasarlandığı şekilde kullanırken, kapatıldığında ne zaman denetleneceğinden, bir yaklaşım ilk olarak dialog.Show () öğesini çağırmak, ardından tıklama işleyicisini geçersiz kılmak için dialog.getButton () düğmesini kullanarak bir başvuru elde etmektir. Başka bir yaklaşım setOnShowListener () kullanmak ve düğme görünümünü bulmak ve OnShowListener'daki işleyiciyi değiştirmek. İkisi arasındaki fonksiyonel fark, diyalog örneğini ilk olarak hangi iş parçacığını oluşturduğuna bağlı olarak 'neredeyse' sıfırdır. Kaynak koduna bakıldığında, onShowListener, bu iletişim kutusunu oluşturan iş parçacığında çalışan bir işleyiciye gönderilen bir mesajla çağrılır. Bu nedenle, OnShowListener'ınız mesaj kuyruğuna gönderilen bir mesajla çağrıldığından, gösteri tamamlandıktan bir süre sonra dinleyicinizi aramanın ertelenmesi teknik olarak mümkündür.
Bu nedenle, en güvenli yaklaşımın ilk olduğuna inanıyorum: show.Dialog () öğesini çağırmak için hemen aynı yürütme yolunda düğme işleyicilerini değiştirin. Show () yöntemini çağıran kodunuz ana GUI iş parçacığında çalışacağı için, show () ile hangi kodu kullanırsanız kullanın, iş parçacığındaki herhangi bir koddan önce yürütülürken OnShowListener yönteminin zamanlaması mesaj kuyruğu.