26

I have an AlertDialog dlgDetails which is shown from another AlertDialog dlgMenu. I would like to be able to show dlgMenu again if the user presses the back button in dlgDetails and simply exit the dialog if he presses outside the dialog.

I think the best way to do this is to override onBackPressed for dlgDetails, but I am not sure how to do that since AlertDialogs must be created indirectly using the Builder.

I am trying to create a derived AlertDialog (public class AlertDialogDetails extends AlertDialog { ...} ) but then I guess I must also extend AlertDialog.Builder in that class to return an AlertDialogDetails, but isn't there a simpler way? And if not, how would you go about overriding the Builder?

Pooks
  • 2,565
  • 3
  • 37
  • 40
  • Well, I found a way to do this by using setOnKeyListener() when creating the dialog, but it still feels like using onBackPressed would be the best way to go. If nobody can come up with a better solution than setOnKeyListener(), then I will post my answer in a few hours (the site won't let me post it now anyway). – Pooks Oct 18 '11 at 09:54
  • I had the same problem. But I was programming in Kotlin. If somebody uses Kotlin, my question will help him/her:https://stackoverflow.com/questions/60462748/not-working-onbackpressed-when-setcancelable-of-alertdialog-is-false – MMG May 18 '20 at 07:10

5 Answers5

64

I finally added a key listener to my dialog to listen to the Back key. Not as elegant as overriding onBackPressed() but it works. Here is the code:

dlgDetails = new AlertDialog.Builder(this)
    .setOnKeyListener(new DialogInterface.OnKeyListener() {
        @Override
        public boolean onKey (DialogInterface dialog, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK && 
                event.getAction() == KeyEvent.ACTION_UP && 
                !event.isCanceled()) {
                dialog.cancel();
                showDialog(DIALOG_MENU);
                return true;
            }
            return false;
        }
    })
    //(Rest of the .stuff ...)

For answer in Kotlin see here:Not working onbackpressed when setcancelable of alertdialog is false

MMG
  • 3,226
  • 5
  • 16
  • 43
Pooks
  • 2,565
  • 3
  • 37
  • 40
  • +1 Thanks for this, it worked well! It is a pity that the method `setOnBackPressed()` does not exist, so I guess this is the easiest way to do it. – Caumons Mar 09 '12 at 13:42
  • Finally a working soulution for my dialog's back button handling. – Adam Varhegyi Mar 26 '12 at 08:32
  • works on BACK button pressed. Doesn't work clicking OUTSIDE the dialog. – dentex Oct 08 '13 at 09:56
  • I had the same problem. But I was programming in Kotlin. If somebody uses Kotlin, my question will help him/her:https://stackoverflow.com/questions/60462748/not-working-onbackpressed-when-setcancelable-of-alertdialog-is-false – MMG May 18 '20 at 07:10
7

Found a shorter solution :) try this:

         accountDialog = builder.create();

        accountDialog.setOnCancelListener(new OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                dialog.dismiss();
                activity.finish();

            }
        });
Lettings Mall
  • 300
  • 3
  • 10
  • That's a pretty good solution, but wouldn't onCancel() be called both when the user presses the back button and when they click outside the dialog? I need to distinguish between those 2 cases. – Pooks Apr 30 '13 at 00:11
  • 1
    This listener is not called when the back button is pressed. – Yoann Hercouet May 06 '13 at 10:53
  • To handle both the BACK button and the click OUTSIDE the dialog: http://stackoverflow.com/a/19244745/1865860 – dentex Oct 08 '13 at 10:06
  • 1
    Note that the setOnCancelListener() is available for API 17 and above. – TheIT May 14 '14 at 23:53
  • I had the same problem. But I was programming in Kotlin. If somebody uses Kotlin, my question will help him/her:https://stackoverflow.com/questions/60462748/not-working-onbackpressed-when-setcancelable-of-alertdialog-is-false – MMG May 18 '20 at 07:10
1

This handles both the BACK button and the click OUTSIDE the dialog:

yourBuilder.setOnCancelListener(new OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        dialog.cancel();
        // do your stuff...
    }
});

dialog.cancel() is the key: with dialog.dismiss() this would handle only the click outside of the dialog, as answered above.

dentex
  • 3,223
  • 4
  • 28
  • 47
  • 1
    I used the OnDismissListener because it handles the back, outside and the negative button too – Nahuel Barrios Nov 09 '16 at 19:37
  • I had the same problem. But I was programming in Kotlin. If somebody uses Kotlin, my question will help him/her:https://stackoverflow.com/questions/60462748/not-working-onbackpressed-when-setcancelable-of-alertdialog-is-false – MMG May 18 '20 at 07:10
0

I created a new function within the java class and made a call to that function from the onClick method of the dialog Builder.

public class Filename extends Activity(){

@Override
onCreate(){
 //your stuff
 //some button click launches Alertdialog
}

public void myCustomDialog(){
 AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
 //other details for builder
      alertDialogBuilder.setNegativeButton("BACK",
            new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
                         dialod.dismiss;
                         myCustomBack();
                    }
      });

 AlertDialog alertDialog = alertDialogBuilder.create();
 alertDialog.setCanceledOnTouchOutside(true);
 alertDialog.show();
}

public void myCustomBack(){
  if(condition1){
    super.onBackPressed();
  }
  if(condition 2){
    //do  stuff here
  }
}

@Override
public void onBackPressed(){
  //handle case here
  if (condition A)
    //Do this
  else 
    //Do that
}

}
Deepak Negi
  • 893
  • 10
  • 19
  • Thanks for the suggestion. However the idea is not to create a negative button called "back", but rather to have a special handling of the phone's back key when the dialog is showing. Handling the activity's onBackPressed does not help because we don't know if the dialog is showing or not without having to add a flag, which is a bit messy. – Pooks Jun 03 '14 at 00:24
  • I had the same problem. But I was programming in Kotlin. If somebody uses Kotlin, my question will help him/her:https://stackoverflow.com/questions/60462748/not-working-onbackpressed-when-setcancelable-of-alertdialog-is-false – MMG May 18 '20 at 07:11
0

Here is an actual solution for C#, based on the answer from Pooks:

First, we have to create a new class for handling the event:

private sealed class KeyListener : Java.Lang.Object, IDialogInterfaceOnKeyListener
{
    private readonly Action _action;

    public KeyListener(Action action)
    {
        _action = action;
    }

    public bool OnKey(IDialogInterface dialog, [GeneratedEnum] Android.Views.Keycode keyCode, KeyEvent e)
    {
        var isBack = keyCode == Android.Views.Keycode.Back
            && e.Action == KeyEventActions.Up
            && !e.IsCanceled;

        if (isBack)
            _action.Invoke();

        return isBack;
    }
}

And we need an action to receive the event:

private void OnBackPressed()
{
    // ... do the stuff
}

Now, we can set up this event:

var dlgDetails = new AlertDialog.Builder(this)
    .SetOnKeyListener(new KeyListener(OnBackPressed))
    // add further set ups
    .Create();