J'ai récemment remarqué ce phénomène dans de nombreuses applications et jeux Android: lorsque vous cliquez sur le bouton Précédent pour "quitter" l'application, un Toast
affiche un message similaire à "Veuillez cliquer à nouveau sur RETOUR pour quitter".
Je me demandais, comme je le vois de plus en plus souvent, est-ce une fonctionnalité intégrée à laquelle vous pouvez en quelque sorte accéder dans une activité? J'ai examiné le code source de nombreuses classes mais je n'arrive pas à trouver quoi que ce soit à ce sujet.
Bien sûr, je peux penser à plusieurs façons de réaliser la même fonctionnalité assez facilement (le plus simple est probablement de garder un booléen dans l'activité qui indique si l'utilisateur a déjà cliqué une fois ...) mais je me demandais s'il y avait déjà quelque chose ici. .
EDIT: Comme l'a mentionné @LAS_VEGAS, je ne voulais pas vraiment dire "sortir" dans le sens traditionnel du terme. (c'est-à-dire terminé) je voulais dire "revenir à ce qui était ouvert avant le lancement de l'activité de démarrage de l'application", si cela a du sens :)
En activité Java:
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);
}
Dans l'activité de Kotlin:
private var doubleBackToExitPressedOnce = false
override fun onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed()
return
}
this.doubleBackToExitPressedOnce = true
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show()
Handler().postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000)
}
Je pense que ce gestionnaire aide à réinitialiser la variable après 2 secondes.
Sudheesh B Nair a une réponse agréable (et acceptée) sur la question, qui, je pense, devrait avoir une meilleure alternative, telle que;
Qu'est-ce qui ne va pas avec le temps passé à mesurer et à vérifier si TIME_INTERVAL
miliseconds (disons 2000) s'est écoulé depuis la dernière presse précédente? L'exemple de code suivant utilise System.currentTimeMillis();
pour stocker l'heure à laquelle onBackPressed()
est appelée;
private static final int TIME_INTERVAL = 2000; // # milliseconds, desired time passed between two back presses.
private long mBackPressed;
@Override
public void onBackPressed()
{
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
super.onBackPressed();
return;
}
else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }
mBackPressed = System.currentTimeMillis();
}
Retour sur la réponse acceptée critique; Utiliser une flag
pour indiquer si elle a été pressée dans le dernier TIME_INTERVAL
(disons 2000) millisecondes et set-reset via la méthode Handler
, la fonction postDelayed()
a été la première chose à venir dans mon esprit. Mais l'action postDelayed()
doit être annulée à la fermeture de l'activité, ce qui supprime la Runnable
.
Afin de supprimer la Runnable
, elle ne doit pas être déclarée anonyme, ni être déclarée en tant que membre avec la Handler
aswell. Ensuite, la méthode removeCallbacks()
de Handler
peut être appelée de manière appropriée.
L’échantillon suivant est la démonstration;
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, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mRunnable, 2000);
}
Merci à @NSouth pour sa contribution; Afin d'éviter que message toast apparaisse même après la fermeture de l'application, Toast
peut être déclaré en tant que membre - disons mExitToast
- et peut être annulé via mExitToast.cancel();
juste avant l'appel super.onBackPressed();
.
Je pensais partager mon travail à la fin, je viens d’ajouter à mon activité:
private boolean doubleBackToExitPressedOnce = false;
@Override
protected void onResume() {
super.onResume();
// .... other stuff in my 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();
}
Et ça marche exactement comme je veux. Y compris la réinitialisation de l'état chaque fois que l'activité est reprise.
Diagramme de flux de processus:
Code Java:
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(), "Press again to exit.",
Toast.LENGTH_SHORT).show();
lastPressedTime = event.getEventTime();
}
return true;
}
}
return false;
}
Il y a moyen très simple parmi toutes ces réponses.
Écrivez simplement le code suivant dans la méthode onBackPressed()
.
long back_pressed;
@Override
public void onBackPressed() {
if (back_pressed + 1000 > System.currentTimeMillis()){
super.onBackPressed();
}
else{
Toast.makeText(getBaseContext(),
"Press once again to exit!", Toast.LENGTH_SHORT)
.show();
}
back_pressed = System.currentTimeMillis();
}
Vous devez définir l'objet back_pressed
en tant que long
dans l'activité.
Sur la base de la réponse correcte et des suggestions formulées dans les commentaires, j'ai créé une démo qui fonctionne parfaitement et supprime les rappels du gestionnaire après son utilisation.
MainActivity.Java
package com.mehuljoisar.d_pressbacktwicetoexit;
import Android.os.Bundle;
import Android.os.Handler;
import Android.app.Activity;
import Android.widget.Toast;
public class MainActivity extends Activity {
private static final long delay = 2000L;
private boolean mRecentlyBackPressed = false;
private Handler mExitHandler = new Handler();
private Runnable mExitRunnable = new Runnable() {
@Override
public void run() {
mRecentlyBackPressed=false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onBackPressed() {
//You may also add condition if (doubleBackToExitPressedOnce || fragmentManager.getBackStackEntryCount() != 0) // in case of Fragment-based add
if (mRecentlyBackPressed) {
mExitHandler.removeCallbacks(mExitRunnable);
mExitHandler = null;
super.onBackPressed();
}
else
{
mRecentlyBackPressed = true;
Toast.makeText(this, "press again to exit", Toast.LENGTH_SHORT).show();
mExitHandler.postDelayed(mExitRunnable, delay);
}
}
}
J'espère que ça vous sera utile !!
Ma solution en utilisant snackbar:
Snackbar mSnackbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final LinearLayout layout = findViewById(R.id.layout_main);
mSnackbar = Snackbar.make(layout, R.string.press_back_again, Snackbar.LENGTH_SHORT);
}
@Override
public void onBackPressed() {
if (mSnackbar.isShown()) {
super.onBackPressed();
} else {
mSnackbar.show();
}
}
Simple et stylé.
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);
Déclarer une variable private boolean doubleBackToExitPressedOnce = false;
Collez ceci dans votre activité principale et cela résoudra votre problème.
Ce n’est pas une bonne idée d’utiliser un Runnable lorsqu’on quitte l’application, j’ai récemment trouvé un moyen beaucoup plus simple d’enregistrer et de comparer la période entre deux clics du bouton BACK. Exemple de code comme suit:
private static long back_pressed_time;
private static long PERIOD = 2000;
@Override
public void onBackPressed()
{
if (back_pressed_time + PERIOD > System.currentTimeMillis()) super.onBackPressed();
else Toast.makeText(getBaseContext(), "Press once again to exit!", Toast.LENGTH_SHORT).show();
back_pressed_time = System.currentTimeMillis();
}
Cela fera l'affaire pour quitter l'application en cliquant deux fois sur le bouton RETOUR dans un certain délai, soit 2000 millisecondes.
La réponse acceptée est Meilleure, mais si vous utilisez Android Design Support Library
, vous pouvez utiliser SnackBar
pour de meilleures vues.
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Snackbar.make(findViewById(R.id.photo_album_parent_view), "Please click BACK again to exit", Snackbar.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
Ce n'est pas une fonctionnalité intégrée. Je pense que ce n'est même pas le comportement recommandé. Les applications Android ne sont pas destinées à quitter:
Pourquoi les applications Android n'offrent-elles pas une option "Quitter"?
Enfin, créez un onBackPressedMethod comme suit:
@Override
public void onBackPressed() {
if (exitToast.getView().isShown()) {
exitToast.cancel();
finish();
} else {
exitToast.show();
}
}
Cela fonctionne correctement, j'ai testé. et je pense que c'est beaucoup plus simple.
Récemment, j'avais besoin de mettre en œuvre cette fonctionnalité de bouton de retour dans une de mes applications. Les réponses à la question initiale étaient utiles, mais je devais prendre en considération deux autres points:
Sur la base des réponses et des commentaires, j'ai créé le code suivant:
private static final long BACK_PRESS_DELAY = 1000;
private boolean mBackPressCancelled = false;
private long mBackPressTimestamp;
private Toast mBackPressToast;
@Override
public void onBackPressed() {
// Do nothing if the back button is disabled.
if (!mBackPressCancelled) {
// Pop fragment if the back stack is not empty.
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
super.onBackPressed();
} else {
if (mBackPressToast != null) {
mBackPressToast.cancel();
}
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp < mBackPressTimestamp + BACK_PRESS_DELAY) {
super.onBackPressed();
} else {
mBackPressTimestamp = currentTimestamp;
mBackPressToast = Toast.makeText(this, getString(R.string.warning_exit), Toast.LENGTH_SHORT);
mBackPressToast.show();
}
}
}
}
Le code ci-dessus suppose que la bibliothèque de support est utilisée. Si vous utilisez des fragments mais pas la bibliothèque de support, vous souhaitez remplacer getSupportFragmentManager()
par getFragmentManager()
.
Supprimez la première if
, si le bouton Précédent n’est jamais annulé. Supprimez la seconde if
, si vous n’utilisez pas de fragments ou une pile de retour de fragments
En outre, il est important de savoir que la méthode onBackPressed
est prise en charge depuis Android 2.0. Vérifiez cette page pour une description détaillée. Pour que la fonction de presse arrière fonctionne également sur les versions antérieures, ajoutez la méthode suivante à votre activité:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (Android.os.Build.VERSION.SDK_INT < Android.os.Build.VERSION_CODES.Eclair
&& keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0) {
// Take care of calling this method on earlier versions of
// the platform where it doesn't exist.
onBackPressed();
}
return super.onKeyDown(keyCode, event);
}
Je sais que c’est une très vieille question, mais c’est la façon la plus simple de faire ce que vous voulez.
@Override
public void onBackPressed() {
++k; //initialise k when you first start your activity.
if(k==1){
//do whatever you want to do on first click for example:
Toast.makeText(this, "Press back one more time to exit", Toast.LENGTH_LONG).show();
}else{
//do whatever you want to do on the click after the first for example:
finish();
}
}
Je sais que ce n'est pas la meilleure méthode, mais cela fonctionne bien!
Cela aide également lorsque l’activité de pile précédente est stockée dans la pile.
J'ai modifié la réponse de Sudheesh
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
//super.onBackPressed();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//***Change Here***
startActivity(intent);
finish();
System.exit(0);
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);
}
Ici, j'ai généralisé écrire le code pour N comptes de prises. Le code est écrit de la même manière pour l'option Activer le développeur sur un téléphone portable Android. Même vous pouvez l'utiliser pour activer des fonctionnalités pendant que les développeurs testent l'application.
private Handler tapHandler;
private Runnable tapRunnable;
private int mTapCount = 0;
private int milSecDealy = 2000;
onCreate(){
...
tapHandler = new Handler(Looper.getMainLooper());
}
Appeler askToExit () en option backpress ou logout.
private void askToExit() {
if (mTapCount >= 2) {
releaseTapValues();
/* ========= Exit = TRUE ========= */
}
mTapCount++;
validateTapCount();
}
/* Check with null to avoid create multiple instances of the runnable */
private void validateTapCount() {
if (tapRunnable == null) {
tapRunnable = new Runnable() {
@Override
public void run() {
releaseTapValues();
/* ========= Exit = FALSE ========= */
}
};
tapHandler.postDelayed(tapRunnable, milSecDealy);
}
}
private void releaseTapValues() {
/* Relase the value */
if (tapHandler != null) {
tapHandler.removeCallbacks(tapRunnable);
tapRunnable = null; /* release the object */
mTapCount = 0; /* release the value */
}
}
@Override
protected void onDestroy() {
super.onDestroy();
releaseTapValues();
}
@Override public void onBackPressed() {
Log.d("CDA", "onBackPressed Called");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
}
A cette fin, j'ai implémenté la fonction suivante:
private long onRecentBackPressedTime;
@Override
public void onBackPressed() {
if (System.currentTimeMillis() - onRecentBackPressedTime > 2000) {
onRecentBackPressedTime = System.currentTimeMillis();
Toast.makeText(this, "Please press BACK again to exit", Toast.LENGTH_SHORT).show();
return;
}
super.onBackPressed();
}
Lorsque HomeActivity contient le tiroir de navigation et la fonction double backPressed () pour quitter app . (N'oubliez pas de lancer la variable globale boolean doubleBackToExitPressedOnce = false;) Nouveau gestionnaire après 2 secondes, définissez la variable doubleBackPressedOnce sur false
@Override
public void onBackPressed() {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.END)) {
drawer.closeDrawer(GravityCompat.END);
} else {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
moveTaskToBack(true);
return;
} else {
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);
}
}
}
En java
private Boolean exit = false;
if (exit) {
onBackPressed();
}
@Override
public void onBackPressed() {
if (exit) {
finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.",
Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
}
à Kotlin
private var exit = false
if (exit) {
onBackPressed()
}
override fun onBackPressed(){
if (exit){
finish() // finish activity
}else{
Toast.makeText(this, "Press Back again to Exit.",
Toast.LENGTH_SHORT).show()
exit = true
Handler().postDelayed({ exit = false }, 3 * 1000)
}
}
Voici le code de travail complet. Et n'oubliez pas de supprimer les rappels afin d'éviter toute fuite de mémoire dans l'application. :)
private boolean backPressedOnce = false;
private Handler statusUpdateHandler;
private Runnable statusUpdateRunnable;
public void onBackPressed() {
if (backPressedOnce) {
finish();
}
backPressedOnce = true;
final Toast toast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT);
toast.show();
statusUpdateRunnable = new Runnable() {
@Override
public void run() {
backPressedOnce = false;
toast.cancel(); //Removes the toast after the exit.
}
};
statusUpdateHandler.postDelayed(statusUpdateRunnable, 2000);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (statusUpdateHandler != null) {
statusUpdateHandler.removeCallbacks(statusUpdateRunnable);
}
}
J'ajouterais normalement un commentaire, mais ma réputation ne le permet pas ... Voici donc mes deux sous:
Dans Kotlin, vous pouvez utiliser des coroutines pour différer le réglage de la valeur false:
private var doubleBackPressed = false
private var toast : Toast ?= null
override fun onCreate(savedInstanceState: Bundle?) {
toast = Toast.maketext(this, "Press back again to exit", Toast.LENGTH_SHORT)
}
override fun onBackPressed() {
if (doubleBackPressed) {
toast?.cancel()
super.onBackPressed()
return
}
this.doubleBackPressed = true
toast?.show()
GlobalScope.launch {
delay(2000)
doubleBackPressed = false
}
}
Vous devrez importer:
import kotlinx.coroutines.launch
import kotlinx.coroutines.delay
import kotlinx.coroutines.GlobalScope
Quelques améliorations dans la réponse de Sudheesh B Nair, j'ai remarqué qu'il attendrait le gestionnaire même en appuyant deux fois immédiatement en arrière, donc annulez le gestionnaire comme indiqué ci-dessous. J'ai également annulé le pain grillé pour l'empêcher de s'afficher après la fermeture de l'application.
boolean doubleBackToExitPressedOnce = false;
Handler myHandler;
Runnable myRunnable;
Toast myToast;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
myHandler.removeCallbacks(myRunnable);
myToast.cancel();
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
myToast = Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT);
myToast.show();
myHandler = new Handler();
myRunnable = new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce = false;
}
};
myHandler.postDelayed(myRunnable, 2000);
}
Dans cette situation, Snackbar est la meilleure option, puis Toast, pour afficher l'action de fermeture. Voici la méthode avec snack qui fonctionne.
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Snackbar.make(this.getWindow().getDecorView().findViewById(Android.R.id.content), "Please click BACK again to exit", Snackbar.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
C'est la même chose pour la réponse acceptée et la plus votée, mais cette capture a utilisé Snackbar au lieu de Toast.
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Snackbar.make(content, "Please click BACK again to exit", Snackbar.LENGTH_SHORT)
.setAction("Action", null).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
Pour l'activité qui a Navigation Drawer , utilisez le code suivant pour OnBackPressed ()
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (doubleBackToExitPressedOnce) {
if (getFragmentManager().getBackStackEntryCount() ==0) {
finishAffinity();
System.exit(0);
} else {
getFragmentManager().popBackStackImmediate();
}
return;
}
if (getFragmentManager().getBackStackEntryCount() ==0) {
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);
} else {
getFragmentManager().popBackStackImmediate();
}
}
}
Voici un autre moyen ... en utilisant la méthode CountDownTimer
private boolean exit = false;
@Override
public void onBackPressed() {
if (exit) {
finish();
} else {
Toast.makeText(this, "Press back again to exit",
Toast.LENGTH_SHORT).show();
exit = true;
new CountDownTimer(3000,1000) {
@Override
public void onTick(long l) {
}
@Override
public void onFinish() {
exit = false;
}
}.start();
}
}
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Snackbar.make(findViewById(R.id.photo_album_parent_view), "Please click BACK again to exit", Snackbar.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
Une méthode légèrement meilleure que Zefnus je pense. Appelez System.currentTimeMillis () une seule fois et omettez return;
:
long previousTime;
@Override
public void onBackPressed()
{
if (2000 + previousTime > (previousTime = System.currentTimeMillis()))
{
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show();
}
}
Dans mon cas, je compte sur Snackbar#isShown()
pour mieux UX
.
private Snackbar exitSnackBar;
@Override
public void onBackPressed() {
if (isNavDrawerOpen()) {
closeNavDrawer();
} else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
if (exitSnackBar != null && exitSnackBar.isShown()) {
super.onBackPressed();
} else {
exitSnackBar = Snackbar.make(
binding.getRoot(),
R.string.navigation_exit,
2000
);
exitSnackBar.show();
}
} else {
super.onBackPressed();
}
}
Dans Kotlin, à l'arrière, appuyez sur pour quitter l'application, vous pouvez utiliser:
Définir une variable globale:
private var doubleBackToExitPressedOnce = false
Remplacer onBackPressed:
override fun onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed()
return
}
doubleBackToExitPressedOnce = true
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_LONG).show()
Handler().postDelayed({
doubleBackToExitPressedOnce = false;
}, 2000)
}
Vous pouvez également utiliser la visibilité d'un pain grillé pour ne pas avoir besoin de cette solution Handler/postDelayed ultra.
Toast doubleBackButtonToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
doubleBackButtonToast = Toast.makeText(this, "Double tap back to exit.", Toast.LENGTH_SHORT);
}
@Override
public void onBackPressed() {
if (doubleBackButtonToast.getView().isShown()) {
super.onBackPressed();
}
doubleBackButtonToast.show();
}
Retour lorsque le bouton est appuyé 2 fois
public void click(View view){
if (isBackActivated) {
this.finish();
}
if (!isBackActivated) {
isBackActivated = true;
Toast.makeText(getApplicationContext(), "Again", Toast.LENGTH_SHORT).show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
isBackActivated = false; // setting isBackActivated after 2 second
}
}, 2000);
}
}
private static final int TIME_INTERVAL = 2000;
private long mBackPressed;
@Override
public void onBackPressed() {
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
super.onBackPressed();
Intent intent = new Intent(FirstpageActivity.this,
HomepageActivity.class);
startActivity(intent);
finish();
return;
} else {
Toast.makeText(getBaseContext(),
"Tap back button twice to go Home.", Toast.LENGTH_SHORT)
.show();
mBackPressed = System.currentTimeMillis();
}
}
Meilleure solution avec du pain grillé
En java
private Toast exitToast;
@Override
public void onBackPressed() {
if (exitToast == null || exitToast.getView() == null || exitToast.getView().getWindowToken() == null) {
exitToast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_LONG);
exitToast.show();
} else {
exitToast.cancel();
super.onBackPressed();
}
}
À Kotlin
private var exitToast: Toast? = null
override fun onBackPressed() {
if (exitToast == null || exitToast!!.view == null || exitToast!!.view.windowToken == null) {
exitToast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_LONG)
exitToast!!.show()
} else {
exitToast!!.cancel()
super.onBackPressed()
}
}
Voici mon point de vue sur ceci:
int oddeven = 0;
long backBtnPressed1;
long backBtnPressed2;
@Override
public void onBackPressed() {
oddeven++;
if(oddeven%2==0){
backBtnPressed2 = System.currentTimeMillis();
if(backBtnPressed2-backBtnPressed1<2000) {
super.onBackPressed();
return;
}
}
else if(oddeven%2==1) {
backBtnPressed1 = System.currentTimeMillis();
// Insert toast back button here
}
}
private static final int TIME_DELAY = 2000;
private static long back_pressed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onBackPressed() {
if (back_pressed + TIME_DELAY > System.currentTimeMillis()) {
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Press once again to exit!",
Toast.LENGTH_SHORT).show();
}
back_pressed = System.currentTimeMillis();
}
Après avoir eu à mettre en œuvre plusieurs fois les mêmes choses, il a été décidé que quelqu'un créerait une bibliothèque simple à utiliser. Et c'est DoubleBackPress Android library
. La README
explique toutes les API fournies avec des exemples (comme ToastDisplay + Exit Activity ), mais décrit brièvement les étapes décrites ici.
Pour commencer, commencez par ajouter la dependency
à votre application:
dependencies {
implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1'
}
Ensuite, créez un objet DoubleBackPress
dans votre Activity
qui fournit le comportement requis.
DoubleBackPress doubleBackPress = new DoubleBackPress();
doubleBackPress.setDoublePressDuration(3000); // msec
Ensuite, créez une Toast
qui doit être affichée sur le Premier Retour Appuyez sur. Ici, vous pouvez créer votre propre Toast
ou aller avec Standard Toast
fourni dans la library
. Ce faisant ici par la dernière option.
FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);
doubleBackPress.setFirstBackPressAction(firstBackPressAction); // set the action
Maintenant, définissez ce qui doit se passer lorsque votre deuxième dos se produit. Ici, nous fermons l'activité.
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() {
@Override
public void actionCall() {
finish();
System.exit(0);
}
};
Enfin, remplacez votre comportement de presse arrière par le comportement DoubleBackPress
.
@Override
public void onBackPressed() {
doubleBackPress.onBackPressed();
}
vous pouvez même le rendre plus simple, et sans utiliser un hander, faites seulement ceci =)
Long firstClick = 1L;
Long secondClick = 0L;
@Override
public void onBackPressed() {
secondClick = System.currentTimeMillis();
if ((secondClick - firstClick) / 1000 < 2) {
super.onBackPressed();
} else {
firstClick = System.currentTimeMillis();
Toast.makeText(MainActivity.this, "click BACK again to exit", Toast.LENGTH_SHORT).show();
}
}
Voici un moyen de le faire en utilisant RxJava:
override fun onCreate(...) {
backPresses.timeInterval(TimeUnit.MILLISECONDS, Schedulers.io())
.skip(1) //Skip initial event; delay will be 0.
.onMain()
.subscribe {
if (it.time() < 7000) super.onBackPressed() //7000 is the duration of a Toast with length LENGTH_LONG.
}.addTo(compositeDisposable)
backPresses.throttleFirst(7000, TimeUnit.MILLISECONDS, Schedulers.io())
.subscribe { Toast.makeText(this, "Press back again to exit.", LENGTH_LONG).show() }
.addTo(compositeDisposable)
}
override fun onBackPressed() = backPresses.onNext(Unit)
Je pense que c'est ce dont vous avez besoin, je veux dire quand nous voulons montrer ce pain grillé, quand il n'y a qu'une seule activité dans la pile et que l'utilisateur appuie en arrière à partir de cette dernière activité de la pile.
var exitOpened=false // Declare it globaly
et dans la méthode onBackPressed
, changez comme suit:
override fun onBackPressed() {
if (isTaskRoot && !exitOpened)
{
exitOpened=true
toast("Please press back again to exit")
return
}
super.onBackPressed()
}
Ici, isTaskRoot
retournera true si l'activité en cours est l'activité racine (première activité) de la pile et false si ce n'est pas le cas.
Vous pouvez consulter la documentation officielle ici