Android: bonne façon d'utiliser onBackPressed () avec Toast

85

J'ai écrit un morceau de code qui donnera à l'utilisateur une invite lui demandant d'appuyer à nouveau s'il souhaite quitter. Actuellement, mon code fonctionne dans une certaine mesure, mais je sais qu'il est mal écrit et je suppose qu'il existe une meilleure façon de le faire. Toute suggestion serait utile!

Code:

public void onBackPressed(){
    backpress = (backpress + 1);
    Toast.makeText(getApplicationContext(), " Press Back again to Exit ", Toast.LENGTH_SHORT).show();

    if (backpress>1) {
        this.finish();
    }
}
pseudo
la source
5
Remplacez this.finish()par super.onBackPressed();.
Fred
5
au lieu d' this.finish()appeler plutôt NavUtils.navigateUpFromSameTask(this);pour revenir à l'écran / l'activité précédente
To Kra

Réponses:

213

J'implémenterais une boîte de dialogue demandant à l'utilisateur s'il voulait quitter, puis appeler super.onBackPressed()s'il le faisait.

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
        .setTitle("Really Exit?")
        .setMessage("Are you sure you want to exit?")
        .setNegativeButton(android.R.string.no, null)
        .setPositiveButton(android.R.string.yes, new OnClickListener() {

            public void onClick(DialogInterface arg0, int arg1) {
                WelcomeActivity.super.onBackPressed();
            }
        }).create().show();
}

Dans l'exemple ci-dessus, vous devrez remplacer WelcomeActivity par le nom de votre activité.

Steve Prentice
la source
cela fonctionne, mais dans mon cas, le popup n'est affiché que pendant quelques millisecondes et après disparaître et la nouvelle fenêtre est affichée. Je n'ai pas le temps de cliquer sur oui ou non, et si je le débogue, cela ne passe pas pour la méthode onClick. Pourquoi?
Accollativo
4
@Accollativo, on dirait que vous avez toujours un appel super.onBackPressed()dans votre onBackPressed()définition (autre que celui à l'intérieur de la méthode onClick)?
Steve Prentice
6
Toutes les applications que j'ai vues favorisent la méthode du "second back press". Un utilisateur appuyant accidentellement sur la touche Retour sera ennuyé si une boîte de dialogue s'affiche. Le pain grillé est moins intrusif.
Karmic Coder
@Steve Prentice J'utilise cet extrait de code dans mon application, mais qu'en est-il si nous avons un processus en cours d'exécution pendant que nous soutenons notre activité - le processus est toujours en cours d'exécution. Comment y remédier? Si j'utilise android.os.Process.killProcess(android.os.Process.myPid());mais l'animation entre les activités n'est pas si fluide. Au lieu de cela, il fait clignoter un écran noir pendant environ la moitié de la seconde.
Stanimir Yakimov
1
@Stanimir Yakimov, examinez les services d'Android pour exécuter les processus d'arrière-plan. Cela facilitera la gestion de votre cycle de vie. Si vous ne parvenez toujours pas à le comprendre, je vous suggère de créer une nouvelle question.
Steve Prentice
19

Vous n'avez pas besoin d'un compteur pour les contre-presses.

Enregistrez simplement une référence au toast affiché:

private Toast backtoast;

Ensuite,

public void onBackPressed() {
    if(USER_IS_GOING_TO_EXIT) {
        if(backtoast!=null&&backtoast.getView().getWindowToken()!=null) {
            finish();
        } else {
            backtoast = Toast.makeText(this, "Press back to exit", Toast.LENGTH_SHORT);
            backtoast.show();
        }
    } else {
        //other stuff...
        super.onBackPressed();
    }
}

Cela s'appellera finish()si vous appuyez sur retour alors que le toast est toujours visible, et uniquement si la pression arrière entraînerait la sortie de l'application.

Siidheesh
la source
au lieu d' this.finish()appeler plutôt NavUtils.navigateUpFromSameTask(this);pour revenir à l'écran / l'activité précédente
To Kra
Une réponse alternative à considérer ici . Je n'ai pas encore décidé quelle approche je préfère. Certains détails de la réponse liée pourraient être ajoutés à celui-ci, en particulier la logique d'annuler le toast dès que l'utilisateur quitte.
ToolmakerSteve
14

J'utilise cette approche beaucoup plus simple ...

public class XYZ extends Activity {
    private long backPressedTime = 0;    // used by onBackPressed()


    @Override
    public void onBackPressed() {        // to prevent irritating accidental logouts
        long t = System.currentTimeMillis();
        if (t - backPressedTime > 2000) {    // 2 secs
            backPressedTime = t;
            Toast.makeText(this, "Press back again to logout",
                                Toast.LENGTH_SHORT).show();
        } else {    // this guy is serious
            // clean up
            super.onBackPressed();       // bye
        }
    }
}
SoloPilot
la source
Quelque chose d'étrange se produit sur une tablette Samsung Note. Besoin de riposter plusieurs fois rapidement. Il n'aime pas non plus l'approche 'backToast' ...
SoloPilot
Cela fonctionne-t-il mieux sur Remarque si vous annulez le toast avant de quitter? Voir ça
ToolmakerSteve
2

Votre chemin et celui de @ Steve sont des moyens acceptables pour éviter les sorties accidentelles.

Si vous choisissez de continuer votre implémentation, vous devrez vous assurer que la contre-pression est initialisée à 0, et probablement implémenter une Timersorte de réinitialisation pour la réinitialiser à 0 lorsque vous appuyez sur une touche, après une période de refroidissement. (~ 5 secondes semble juste)

oui
la source
2

Vous devrez peut-être également réinitialiser le compteur onPausepour éviter les cas où l'utilisateur appuie sur la maison ou s'éloigne par d'autres moyens après la première pression arrière. Sinon, je ne vois pas de problème.

Alex Gitelman
la source
1

Si vous souhaitez quitter votre application de la deuxième activité directe sans accéder à la première activité, essayez ce code..`

Dans la deuxième activité, mettez ce code.

 @Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
            .setTitle("Really Exit?")
            .setMessage("Are you sure you want to exit?")
            .setNegativeButton(android.R.string.no, null)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface arg0, int arg1) {
                    setResult(RESULT_OK, new Intent().putExtra("EXIT", true));
                    finish();
                }

            }).create().show();
}

Et votre première activité Mettez ce code .....

public class FirstActivity extends AppCompatActivity {

Button next;
private final static int EXIT_CODE = 100;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    next = (Button) findViewById(R.id.next);
    next.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {

            startActivityForResult(new Intent(FirstActivity.this, SecondActivity.class), EXIT_CODE);
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == EXIT_CODE) {
        if (resultCode == RESULT_OK) {
            if (data.getBooleanExtra("EXIT", true)) {
                finish();
            }
        }
    }
}

}

Tabish Khan
la source
1

C'est le meilleur moyen, car si l'utilisateur ne recule pas de plus de deux secondes, réinitialise la valeur rétractée.

déclarer une variable globale.

 private boolean backPressToExit = false;

Remplacer la onBackPressedméthode.

@Override
public void onBackPressed() {

    if (backPressToExit) {
        super.onBackPressed();
        return;
    }
    this.backPressToExit = true;
    Snackbar.make(findViewById(R.id.yourview), getString(R.string.exit_msg), Snackbar.LENGTH_SHORT).show();
    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            backPressToExit = false;
        }
    }, 2000);
}
Yogesh Rathi
la source
déclarer une variable comme une booléenne privée backPressToExit = false
Yogesh Rathi
1) Veuillez modifier votre réponse pour inclure le booléen que vous mentionnez, plutôt que de le dire dans un commentaire. Ainsi, les gens peuvent voir où doit se trouver la déclaration. 2) En effet, c'est une manière alternative d'être conscient du temps. Veuillez expliquer pourquoi vous considérez cela comme «meilleur». Plus précisément, cela entraîne la création d'un gestionnaire - que gagne-t-on en faisant cela?
ToolmakerSteve
0

de plus, vous devez afficher la boîte de dialogue avant d'appeler activity.super.onBackPressed(), sinon vous obtiendrez l'erreur "Activité a fui ..".

Exemple dans mon cas avec la bibliothèque sweetalerdialog:

 @Override
    public void onBackPressed() {
        //super.onBackPressed();
        SweetAlertDialog progressDialog = new SweetAlertDialog(this, SweetAlertDialog.WARNING_TYPE);
        progressDialog.setCancelable(false);
        progressDialog.setTitleText("Are you sure you want to exit?");
        progressDialog.setCancelText("No");
        progressDialog.setConfirmText("Yes");
        progressDialog.setCanceledOnTouchOutside(true);
        progressDialog.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
            @Override
            public void onClick(SweetAlertDialog sweetAlertDialog) {
                sweetAlertDialog.dismiss();
                MainActivity.super.onBackPressed();
            }
        });
        progressDialog.show();
    }
kaMChy
la source
0

utiliser pour .onBackPressed () pour sauvegarder l'activité spécifier

@Override
public void onBackPressed(){
    backpress = (backpress + 1);
    Toast.makeText(getApplicationContext(), " Press Back again to Exit ", Toast.LENGTH_SHORT).show();

    if (backpress>1) {
        this.finish();
    }
}
M.zar
la source
1
Veuillez expliquer ce que vous avez ajouté au code d'origine et pourquoi.
ToolmakerSteve
0

Je viens d'avoir ce problème et je l'ai résolu en ajoutant la méthode suivante:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
             // click on 'up' button in the action bar, handle it here
             return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}    
Marc
la source
0

Vous pouvez également utiliser onBackPressed de différentes manières en utilisant Toast personnalisé:

entrez la description de l'image ici

custom_toast.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/txtMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableStart="@drawable/ic_white_exit_small"
    android:drawableLeft="@drawable/ic_white_exit_small"
    android:drawablePadding="8dp"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:gravity="center"
    android:textColor="@android:color/white"
    android:textSize="16sp"
    android:text="Press BACK again to exit.."
    android:background="@drawable/curve_edittext"/>

MainActivity.java

@Override
public void onBackPressed() {

    if (doubleBackToExitPressedOnce) {
        android.os.Process.killProcess(Process.myPid());
        System.exit(1);
        return;
    }

    this.doubleBackToExitPressedOnce = true;
    Toast toast = new Toast(Dashboard.this);
    View view = getLayoutInflater().inflate(R.layout.toast_view,null);
    toast.setView(view);
    toast.setDuration(Toast.LENGTH_SHORT);
    int margin = getResources().getDimensionPixelSize(R.dimen.toast_vertical_margin);
    toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_VERTICAL, 0, margin);
    toast.show();

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

        @Override
        public void run() {
            doubleBackToExitPressedOnce=false;
        }
    }, 2000);
}
Pankaj Lilan
la source
0

Utilisez ceci, cela peut aider.

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
            .setTitle("Message")
            .setMessage("Do you want to exit app?")
            .setNegativeButton("NO", null)
            .setPositiveButton("YES", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    UserLogin.super.onBackPressed();
                }
            }).create().show();
}
Manisa
la source