Android: Richtige Verwendung von onBackPressed () mit Toast

85

Ich habe einen Code geschrieben, der den Benutzer auffordert, ihn erneut zu drücken, wenn er das Programm beenden möchte. Ich habe derzeit einen gewissen Code, aber ich weiß, dass er schlecht geschrieben ist, und ich gehe davon aus, dass es einen besseren Weg gibt, dies zu tun. Anregungen wäre hilfreich!

Code:

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

    if (backpress>1) {
        this.finish();
    }
}
Nick
quelle
5
Ersetzen this.finish()durch super.onBackPressed();.
Fred
5
anstatt this.finish()lieber anzurufen NavUtils.navigateUpFromSameTask(this);, um zum vorherigen Bildschirm / zur vorherigen Aktivität zurückzukehren
An Kra

Antworten:

211

Ich würde einen Dialog implementieren, der den Benutzer fragt, ob er beenden möchte, und dann anrufen, super.onBackPressed()wenn er dies tut.

@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();
}

Im obigen Beispiel müssen Sie WelcomeActivity durch den Namen Ihrer Aktivität ersetzen.

Steve Prentice
quelle
Dies funktioniert, aber in meinem Fall wird das Popup nur für einige Millisekunden angezeigt und nach dem Verschwinden wird das neue Fenster angezeigt. Ich habe nicht die Zeit, auf Ja oder Nein zu klicken, und wenn ich es debugge, gilt es nicht für die onClick-Methode. Warum?
Accollativo
4
@Accollativo, hört sich so an, als hätten Sie super.onBackPressed()in Ihrer onBackPressed()Definition immer noch einen Aufruf (außer dem in der onClick-Methode)?
Steve Prentice
6
Jede App, die ich gesehen habe, bevorzugt die "Second Back Press" -Methode. Ein Benutzer, der versehentlich die Zurück-Taste drückt, wird verärgert, wenn ein Dialogfeld angezeigt wird. Der Toast ist weniger aufdringlich.
Karmic Coder
@Steve Prentice Ich verwende dieses Snippet in meiner Anwendung, aber was ist, wenn wir einen laufenden Prozess haben, während wir unsere Aktivität unterstützen - der Prozess läuft noch. Wie kann man das beheben? Wenn ich android.os.Process.killProcess(android.os.Process.myPid());aber benutze , ist die Animation zwischen den Aktivitäten nicht so flüssig. Stattdessen blinkt etwa die Hälfte der Sekunde ein schwarzer Bildschirm.
Stanimir Yakimov
1
@ Stanimir Yakimov, schauen Sie sich die Dienste von Android für die Ausführung von Hintergrundprozessen an. Das erleichtert Ihnen das Lebenszyklusmanagement. Wenn Sie es immer noch nicht herausfinden können, würde ich vorschlagen, eine neue Frage zu erstellen.
Steve Prentice
19

Sie benötigen keinen Zähler für Rückpressen.

Speichern Sie einfach einen Verweis auf den angezeigten Toast:

private Toast backtoast;

Dann,

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();
    }
}

Dies wird aufgerufen, finish()wenn Sie zurück drücken, während der Toast noch sichtbar ist, und nur, wenn das Zurückdrücken zum Beenden der Anwendung führen würde.

Siidheesh
quelle
anstatt this.finish()lieber anzurufen NavUtils.navigateUpFromSameTask(this);, um zum vorherigen Bildschirm / zur vorherigen Aktivität zurückzukehren
An Kra
Eine alternative Antwort, die hier zu berücksichtigen ist . Ich habe mich noch nicht entschieden, welchen Ansatz ich bevorzuge. Einige Details der verknüpften Antwort könnten zu dieser hinzugefügt werden, insbesondere die Logik, den Toast abzubrechen, sobald der Benutzer beendet wird.
ToolmakerSteve
14

Ich benutze diesen viel einfacheren Ansatz ...

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
quelle
Auf einem Samsung Note Tablet passiert etwas Seltsames. Müssen mehrmals schnell zurückschlagen. Es mag auch nicht den 'backToast'-Ansatz ...
SoloPilot
Funktioniert es bei Note besser, wenn Sie den Toast vor dem Beenden abbrechen? Siehe dies
ToolmakerSteve
2

Sowohl Ihr Weg als auch der von @ Steve sind akzeptable Wege, um versehentliche Ausgänge zu verhindern.

Wenn Sie mit der Implementierung fortfahren möchten, müssen Sie sicherstellen, dass der Backpress auf 0 initialisiert ist, und wahrscheinlich eine TimerArt implementieren , um ihn nach einer Abklingzeit beim Tastendruck wieder auf 0 zurückzusetzen. (~ 5 Sekunden scheint richtig)

ja
quelle
2

Möglicherweise müssen Sie auch den Zähler zurücksetzen onPause, um Fälle zu vermeiden, in denen der Benutzer nach dem ersten Zurückdrücken nach Hause drückt oder auf andere Weise weg navigiert. Ansonsten sehe ich kein Problem.

Alex Gitelman
quelle
1

Wenn Sie Ihre Anwendung aus der direkten zweiten Aktivität beenden möchten, ohne zur ersten Aktivität zu wechseln, versuchen Sie diesen Code. "

In der zweiten Aktivität geben Sie diesen Code ein.

 @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();
}

Und Ihre erste Aktivität Geben Sie diesen Code ein .....

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
quelle
1

Dies ist der beste Weg, denn wenn der Benutzer nicht länger als zwei Sekunden zurück ist, setzen Sie den zurückgedrückten Wert zurück.

Deklarieren Sie eine globale Variable.

 private boolean backPressToExit = false;

onBackPressedMethode überschreiben .

@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
quelle
Deklarieren Sie eine Variable wie als private boolesche backPressToExit = false
Yogesh Rathi
1) Bitte bearbeiten Sie Ihre Antwort so, dass sie den von Ihnen erwähnten Booleschen Wert enthält, anstatt dies in einem Kommentar zu sagen. So können die Leute sehen, wo die Erklärung sein sollte. 2) Dies ist in der Tat eine alternative Möglichkeit, sich der Zeit bewusst zu werden. Bitte erläutern Sie, warum Sie dies als "am besten" betrachten. Dies hat insbesondere den Aufwand, einen Handler zu erstellen - was wird dadurch erreicht?
ToolmakerSteve
0

Außerdem müssen Sie den Dialog vor dem Aufruf auflösen activity.super.onBackPressed(), da sonst der Fehler "Aktivität ist durchgesickert ..." angezeigt wird.

Beispiel in meinem Fall mit der Sweetalerdialog-Bibliothek:

 @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
quelle
0

Verwenden Sie .onBackPressed (), um die angegebene Aktivität zu unterstützen

@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
quelle
1
Bitte erläutern Sie, was Sie dem Originalcode hinzugefügt haben und warum.
ToolmakerSteve
0

Ich hatte gerade dieses Problem und löste es durch Hinzufügen der folgenden Methode:

@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
quelle
0

Sie können onBackPressed auch auf folgende Weise mit benutzerdefiniertem Toast verwenden:

Geben Sie hier die Bildbeschreibung ein

customized_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
quelle
0

Verwenden Sie dies, es kann helfen.

@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
quelle