web-dev-qa-db-fra.com

Comment afficher une boîte de dialogue pour confirmer que l'utilisateur souhaite quitter une activité Android?

J'ai essayé de montrer un "Voulez-vous quitter?" type de boîte de dialogue lorsque l'utilisateur tente de quitter une activité. 

Cependant, je ne trouve pas les hooks d'API appropriés. Activity.onUserLeaveHint() semblait initialement prometteur, mais je ne trouve pas le moyen d'arrêter l'activité.

261
Peter A

Dans Android 2.0+, cela ressemblerait à ceci:

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
        .setIcon(Android.R.drawable.ic_dialog_alert)
        .setTitle("Closing Activity")
        .setMessage("Are you sure you want to close this activity?")
        .setPositiveButton("Yes", new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            finish();    
        }

    })
    .setNegativeButton("No", null)
    .show();
}

Dans les versions précédentes, cela ressemblerait à:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    //Handle the back button
    if(keyCode == KeyEvent.KEYCODE_BACK) {
        //Ask the user if they want to quit
        new AlertDialog.Builder(this)
        .setIcon(Android.R.drawable.ic_dialog_alert)
        .setTitle(R.string.quit)
        .setMessage(R.string.really_quit)
        .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

                //Stop the activity
                YourClass.this.finish();    
            }

        })
        .setNegativeButton(R.string.no, null)
        .show();

        return true;
    }
    else {
        return super.onKeyDown(keyCode, event);
    }

}
380
jax
@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
           .setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   ExampleActivity.super.onBackPressed();
               }
           })
           .setNegativeButton("No", null)
           .show();
}
174
Chanakya Vadla

Avoir modifié le code @ user919216 .. et le rendre compatible avec WebView

@Override
public void onBackPressed() {
    if (webview.canGoBack()) {
        webview.goBack();

    }
    else
    {
     AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
       .setCancelable(false)
       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                finish();
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
           }
       });
AlertDialog alert = builder.create();
alert.show();
    }

}
32
suraj jain

Je préférerais quitter en appuyant deux fois sur le bouton retour plutôt qu'avec un dialogue de sortie.

Dans cette solution, un pain grillé apparaît lorsque vous revenez pour la première fois, avertissant qu'une autre pression sur la touche arrière fermera l'application. Dans cet exemple, moins de 4 secondes.

private Toast toast;
private long lastBackPressTime = 0;

@Override
public void onBackPressed() {
  if (this.lastBackPressTime < System.currentTimeMillis() - 4000) {
    toast = Toast.makeText(this, "Press back again to close this app", 4000);
    toast.show();
    this.lastBackPressTime = System.currentTimeMillis();
  } else {
    if (toast != null) {
    toast.cancel();
  }
  super.onBackPressed();
 }
}

Jeton de: http://www.androiduipatterns.com/2011/03/back-button-behavior.html

22
Toni Gamez

Si vous ne savez pas si l'appel à "retour" va quitter l'application ou amener l'utilisateur à une autre activité, vous pouvez envelopper les réponses ci-dessus dans une vérification, isTaskRoot (). Cela peut se produire si votre activité principale peut être ajoutée plusieurs fois à la pile arrière ou si vous manipulez l'historique de cette pile. 

if(isTaskRoot()) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure you want to exit?")
       .setCancelable(false)
       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                YourActivity.super.onBackPressed;
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
           }
       });
    AlertDialog alert = builder.create();
    alert.show();

} else {
    super.onBackPressed();
}
20
GLee

en Chine, la plupart des applications confirmeront la sortie par "cliquer deux fois": 

boolean doubleBackToExitPressedOnce = false;

@Override
public void onBackPressed() {
    if (doubleBackToExitPressedOnce) {
        super.onBackPressed();
        return;
    }

    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();

    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            doubleBackToExitPressedOnce=false;                       
        }
    }, 2000);
} 
5

Supprimez d'abord super.onBackPressed(); de la méthode onbackPressed() que et sous le code:

@Override
public void onBackPressed() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    MyActivity.this.finish();
               }
           })
           .setNegativeButton("No", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
               }
           });
    AlertDialog alert = builder.create();
    alert.show();

}
5
Anjali-Systematix

Utilisation de Lambda:

    new AlertDialog.Builder(this).setMessage(getString(R.string.exit_msg))
        .setTitle(getString(R.string.info))
        .setPositiveButton(getString(R.string.yes), (arg0, arg1) -> {
            moveTaskToBack(true);
            finish();
        })
        .setNegativeButton(getString(R.string.no), (arg0, arg1) -> {
        })
        .show();

Vous devez également définir un langage de niveau pour prendre en charge Java 8 dans votre fichier gradle.build:

compileOptions {
       targetCompatibility 1.8
       sourceCompatibility 1.8
}
5
vasiljevski
Just put this code in your first activity 

@Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.END)) {
            drawerLayout.closeDrawer(GravityCompat.END);
        }
        else {
// if your using fragment then you can do this way
            int fragments = getSupportFragmentManager().getBackStackEntryCount();
            if (fragments == 1) {
new AlertDialog.Builder(this)
           .setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    finish();
               }
           })
           .setNegativeButton("No", null)
           .show();


            } else {
                if (getFragmentManager().getBackStackEntryCount() > 1) {
                    getFragmentManager().popBackStack();
                } else {

           super.onBackPressed();
                }
            }
        }
    }
2
Mohit Hooda

J'aime une approche @GLee et l'utiliser avec fragment comme ci-dessous.

@Override
public void onBackPressed() {
    if(isTaskRoot()) {
        new ExitDialogFragment().show(getSupportFragmentManager(), null);
    } else {
        super.onBackPressed();
    }
}

Dialogue à l'aide de Fragment:

public class ExitDialogFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
            .setTitle(R.string.exit_question)
            .setPositiveButton(Android.R.string.yes, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    getActivity().finish();
                }
            })
            .setNegativeButton(Android.R.string.no, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    getDialog().cancel();
                }
            })
            .create();
    }
}
2
marioosh

cela fonctionne bien

@Override
public void onBackPressed() {
    if (mExitOnBackPress) finish();
    else {
        Toast.makeText(this, R.string.msg_confirm_exit, Toast.LENGTH_SHORT).show();
        mExitOnBackPress = true;
        new Android.os.Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mExitOnBackPress = false;
            }
        }, 2000);
    }
}
1
user3896501

Une autre solution consisterait à afficher un Toast/Snackbar sur la première pression en arrière et demander à nouveau de quitter jusqu'à Quitter, ce qui est beaucoup moins intrusif que de montrer AlertDialog pour confirmer si l'utilisateur souhaite quitter l'application.

Vous pouvez utiliser le DoubleBackPress Android Library pour y parvenir avec quelques lignes de code. Exemple GIF montrant un comportement similaire.

Pour commencer, ajoutez la dépendance à votre application:

dependencies {
    implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1'
}

Ensuite, dans votre activité, implémentez le comportement requis.

// set the Toast to be shown on FirstBackPress (ToastDisplay - builtin template)
// can be replaced by custom action (new FirstBackPressAction{...})
FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);

// set the Action on DoubleBackPress
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() {
    @Override
    public void actionCall() {
        // TODO : Exit the application
        finish();
        System.exit(0);
    }
};

// setup DoubleBackPress behaviour : close the current Activity
DoubleBackPress doubleBackPress = new DoubleBackPress()
        .withDoublePressDuration(3000)     // msec - wait for second back press
        .withFirstBackPressAction(firstBackPressAction)
        .withDoubleBackPressAction(doubleBackPressAction);

Enfin, définissez ceci comme comportement lors du retour en arrière.

@Override
public void onBackPressed() {
    doubleBackPress.onBackPressed();
}
1
Kaushik NP

SI vous utilisez fragment au lieu d'activité mettez ce code dans votre activité principale 

    private Toast toast;
    private long lastBackPressTime = 0;
    @SuppressLint("WrongConstant")
    @Override
    public void onBackPressed() {
        int fragments = getFragmentManager().getBackStackEntryCount();
        if (fragments == 0) {
            // make layout invisible since last fragment will be removed
            if (this.lastBackPressTime < System.currentTimeMillis() - 3000) {
                toast = Toast.makeText(this, "Press back again to close this app", 3000);
                toast.show();
                this.lastBackPressTime = System.currentTimeMillis();

            }else{
                if (toast != null) {
                    toast.cancel();
                }
                super.onBackPressed();
            }

        }else{
            if (toast != null) {
                toast.cancel();
            }
            super.onBackPressed();
        }
    }
0
Firefog

Si vous utilisez fragment dans votre application, voici la solution

@Override
        public void onBackPressed() {

            int count = getSupportFragmentManager().getBackStackEntryCount();//User that use Android library should use getFragmentManager()


            if (count == 0) {
                new AlertDialog.Builder(this)
                        .setTitle(getString(R.string.closing_app))
                        .setMessage(getString(R.string.closing_app_msg))
                        .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }

                        })
                        .setNegativeButton(getString(R.string.no), null)
                        .show();

            }
            else {
                super.onBackPressed();
            }
        }
0
Beyaz

Pour afficher la boîte de dialogue afin de confirmer que l'utilisateur souhaite quitter une activité Android.

Ajoutez le code ci-dessous à la méthode de remplacement onBackPressed.

@Override
        public void onBackPressed() {

                hideViews();
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);

                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Are you sure you want to exit the activity?")
                        .setCancelable(false)
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                                    finishAffinity();
                                }
                            }
                        })
                        .setNegativeButton("No", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                            }
                        });
                AlertDialog alert = builder.create();
                alert.show();

        }

J'espère que son aide pour vous.

0
Android Geek