389 Stimmen

Durch zweimaliges Klicken auf die Zurück-Schaltfläche verlassen Sie eine Aktivität.

Ich habe in letzter Zeit dieses Muster in vielen Android-Apps und Spielen bemerkt: Beim Klicken auf die Zurück-Schaltfläche, um die Anwendung zu "beenden", erscheint eine Toast mit einer Nachricht ähnlich wie "Bitte klicken Sie erneut auf ZURÜCK, um zu beenden".

Ich frage mich, da ich es immer öfter sehe, ob das eine eingebaute Funktion ist, auf die man auf irgendeine Weise in einer Aktivität zugreifen kann. Ich habe den Quellcode vieler Klassen durchgesehen, konnte jedoch nichts darüber finden.

Natürlich kann ich mir ein paar Möglichkeiten vorstellen, um die gleiche Funktionalität recht einfach zu erreichen (das einfachste ist wahrscheinlich, einen Boolean in der Aktivität zu halten, der anzeigt, ob der Benutzer bereits einmal geklickt hat...), aber ich frage mich, ob es bereits etwas gibt.

BEARBEITEN: Wie @LAS_VEGAS erwähnt hat, meinte ich mit "beenden" nicht im traditionellen Sinne. (d.h. beendet) Ich meinte "zurück zu dem, was geöffnet war, bevor die Startaktivität der Anwendung gestartet wurde", wenn das Sinn macht :)

0 Stimmen

[Android - Bestätigung des App-Austritts mit Toast] [1]: stackoverflow.com/questions/14006461/…

1 Stimmen

Ich hatte das gleiche Problem beim Verwenden der HoloEverywhere-Bibliothek, zu einfach können Sie android:launchMode="singleTask" zur Aktivitätsdefinition in der Manifestdatei hinzufügen.

0 Stimmen

1063voto

Sudheesh B Nair Punkte 10963

In Java-Aktivität:

boolean doubleBackToExitPressedOnce = false;

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

    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "Bitte klicken Sie erneut auf ZURÜCK, um zu beenden", Toast.LENGTH_SHORT).show();

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

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

In Kotlin-Aktivität:

private var doubleBackToExitPressedOnce = false
override fun onBackPressed() {
        if (doubleBackToExitPressedOnce) {
            super.onBackPressed()
            return
        }

        this.doubleBackToExitPressedOnce = true
        Toast.makeText(this, "Bitte klicken Sie erneut auf ZURÜCK, um zu beenden", Toast.LENGTH_SHORT).show()

        Handler(Looper.getMainLooper()).postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000)
    }

Ich denke, dieser Handler hilft dabei, die Variable nach 2 Sekunden zurückzusetzen.

50 Stimmen

Beste Antwort! Du kannst auch die Bedingung hinzufügen if (doubleBackToExitPressedOnce || fragmentManager.getBackStackEntryCount() != 0) { im Falle von Fragment-basierten fügen

2 Stimmen

Ich stimme zu, dies ist definitiv die beste Antwort und sollte als akzeptierte Antwort markiert werden.

3 Stimmen

Du solltest das Runnable entfernen, wenn die Anwendung beendet wird.

255voto

Saro Taşciyan Punkte 5192

Sudheesh B Nair hat eine gute (und akzeptierte) Antwort auf die Frage, die ich für eine bessere Alternative halte, wie zum Beispiel;

Was ist falsch daran, die vergangene Zeit zu messen und zu überprüfen, ob TIME_INTERVAL Millisekunden (sagen wir 2000) seit dem letzten Zurückdrücken vergangen sind. Der folgende Beispielcode verwendet System.currentTimeMillis(); um die Zeit zu speichern, wenn onBackPressed() aufgerufen wird;

private static final int TIME_INTERVAL = 2000; // # Millisekunden, gewünschte Zeit zwischen zwei Zurück-Drücken.
private long mBackPressed;

@Override
public void onBackPressed()
{
    if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) 
    { 
        super.onBackPressed(); 
        return;
    }
    else { Toast.makeText(getBaseContext(), "Tippen Sie auf die Zurück-Taste, um zu beenden", Toast.LENGTH_SHORT).show(); }

    mBackPressed = System.currentTimeMillis();
}

Zurück zur akzeptierten Antwort Kritik; Die Verwendung einer flag um anzuzeigen, ob sie in den letzten TIME_INTERVAL (sagen wir 2000) Millisekunden gedrückt wurde und das Festlegen - Zurücksetzen erfolgt über Handler's postDelayed() Methode war das erste, was mir in den Sinn kam. Aber die postDelayed() Aktion sollte abgebrochen werden, wenn die Aktivität geschlossen wird, indem der Runnable entfernt wird.

Um den Runnable zu entfernen, darf er nicht anonym deklariert sein und muss zusammen mit dem Handler als Mitglied deklariert werden. Dann kann die Methode removeCallbacks() des Handlers entsprechend aufgerufen werden.

Das folgende Beispiel ist die Demonstration;

private boolean doubleBackToExitPressedOnce;
private Handler mHandler = new Handler();

private final Runnable mRunnable = new Runnable() {
    @Override
    public void run() {
        doubleBackToExitPressedOnce = false;                       
    }
};

@Override 
protected void onDestroy() 
{ 
    super.onDestroy();

    if (mHandler != null) { mHandler.removeCallbacks(mRunnable); }
}

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

    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "Bitte nochmal auf ZURÜCK klicken, um zu beenden", Toast.LENGTH_SHORT).show();

    mHandler.postDelayed(mRunnable, 2000);
}

Danke an @NSouth für den Beitrag; Um zu verhindern, dass die Toast-Meldung auch nachdem die Anwendung geschlossen wurde weiterhin erscheint, kann Toast als Mitglied deklariert werden - sagen wir mExitToast - und kann über mExitToast.cancel(); kurz vor dem Aufruf von super.onBackPressed(); abgebrochen werden.

12 Stimmen

Für diejenigen, die denken, dass das, was Sudheesh B Nair gesagt hat, dasselbe ist: Gleiche Funktionalität, bessere Leistung. also +1.

4 Stimmen

Ich mag diese Antwort und ich denke, sie ist die beste. Ich meine nicht, dass ich denke, es ist die beste Antwort, aus den oben genannten Gründen. Ich hoffe, du bekommst mehr Upvotes für diese. Ein Kommentar jedoch: Findet es niemand seltsam, dass der Toast einige Sekunden bestehen bleibt, nachdem die App geschlossen wurde? Ist es niemandem wichtig, den Toast abzubrechen? Ich weiß, es mag ein kleines Detail sein, aber ich denke, das sollte passieren. Was denkt ihr?

0 Stimmen

@acrespo Danke. Du hast recht, es sieht komisch aus, wenn der Toast weiterhin erscheint, nachdem die Anwendung beendet wurde. Vielleicht kümmert es die meisten Benutzer nicht, weil es passiert. In Android erscheinen Toast-Nachrichten im Launcher und das ist normal.

31voto

Guillaume Punkte 22444

Ich dachte, ich würde teilen, wie ich es am Ende gemacht habe, ich habe einfach meine Aktivität hinzugefügt:

private boolean doubleBackToExitPressedOnce = false;

@Override
protected void onResume() {
    super.onResume();
    // .... andere Dinge in meinem onResume ....
    this.doubleBackToExitPressedOnce = false;
}

@Override
public void onBackPressed() {
    if (doubleBackToExitPressedOnce) {
        super.onBackPressed();
        return;
    }
    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, R.string.exit_press_back_twice_message, Toast.LENGTH_SHORT).show();
}

Und es funktioniert genau so, wie ich es möchte. Einschließlich des Zurücksetzens des Zustands, wenn die Aktivität fortgesetzt wird.

20 Stimmen

Mit dieser Lösung können die beiden Zurück-Tasten ein beliebiges Zeitintervall zwischen sich haben. So können Sie einmal auf Zurück drücken und dann eine Minute später erneut auf Zurück drücken und die Anwendung wird beendet. Dies ist nicht das Verhalten, das der Benutzer erwarten wird.

1 Stimmen

Ich denke, es ist eine Geschmacksache. In diesem Fall benachrichtigen Sie den Benutzer nur einmal, damit der Benutzer weiß, dass er sich in der Hauptaktivität befindet und ein weiterer Rückruf die App beendet (wahrscheinlich nachdem der Benutzer einige Male zurück gedrückt hat, um zum Hauptbildschirm zurückzukehren). Wenn der Benutzer später erneut auf Zurück drückt, können wir annehmen, dass er die App beenden möchte (es sei denn, er hat in andere Aktivitäten navigiert und wahrscheinlich den Überblick darüber verloren, wie tief er gekommen ist). In der obigen akzeptierten Antwort wird angenommen, dass der Benutzer möglicherweise vergisst, dass er sich bereits im Hauptbildschirm befindet. Beides ist in Ordnung, je nachdem, was Sie möchten oder wie Sie es betrachten.

4 Stimmen

@FerranMaylinch - Ich widerspreche. Dies ist nicht nur eine Frage des Geschmacks. Wenn eine signifikante Zeit vergangen ist, sollten wir davon ausgehen, dass der Benutzer in der Zwischenzeit andere Aktionen ausgeführt hat und nicht mehr in Betracht zieht, was er zuvor getan hat und entschieden hat, nicht fortzufahren. Tatsächlich wird fast kein Benutzer noch daran denken, dass er das zuvor getan hat. Ohne Zeitbegrenzung haben Sie die App im Unsichtbarkeitsmodus gelassen, von dem der Benutzer nichts weiß. Ich betrachte das definitiv als schlechtes Benutzeroberflächendesign. Benutzer werden überrascht sein.

28voto

Chintan Rathod Punkte 25518

Es gibt auf alle diese Antworten einen sehr einfachen Weg.

Schreiben Sie einfach folgenden Code innerhalb der onBackPressed() Methode.

long back_pressed;

@Override
public void onBackPressed() {
    if (back_pressed + 1000 > System.currentTimeMillis()){
        super.onBackPressed();
    }
    else{
        Toast.makeText(getBaseContext(),
                "Drücken Sie erneut, um zu beenden!", Toast.LENGTH_SHORT)
                .show();
    }
    back_pressed = System.currentTimeMillis();
}

Sie müssen das back_pressed Objekt als long in der Aktivität definieren.

27voto

vHow Punkte 691

Prozessflussdiagramm: Erneut drücken, um zu verlassen.

Java-Code:

private long lastPressedTime;
private static final int PERIOD = 2000;

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        switch (event.getAction()) {
        case KeyEvent.ACTION_DOWN:
            if (event.getDownTime() - lastPressedTime < PERIOD) {
                finish();
            } else {
                Toast.makeText(getApplicationContext(), "Erneut drücken, um zu beenden.",
                        Toast.LENGTH_SHORT).show();
                lastPressedTime = event.getEventTime();
            }
            return true;
        }
    }
    return false;
}

1 Stimmen

Ich habe dies zunächst als hilfreich eingestuft. Das Problem ist jedoch, dass es aus irgendeinem Grund auf einigen Handys nicht funktioniert. Die onBackPressed-Methode funktioniert am besten, aber dann haben Sie keine Zeitstempel, sodass Sie die Handler benötigen, wie es die akzeptierte Antwort sagt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X