Clicking the back button twice to exit an activity
我最近在很多Android应用和游戏中都注意到了这种模式:当点击后退按钮"退出"应用程序时,
我想知道,因为我越来越频繁地看到它是一个内置的功能,你可以以某种方式访问活动? 我查看了许多类的源代码,但我似乎无法找到任何相关内容。
当然,我可以考虑几种方法来轻松实现相同的功能(最容易的是在活动中保留一个布尔值,表明用户是否已经点击过一次......)但是我想知道这里是否有东西。
编辑:正如@LAS_VEGAS所说,我并不是指传统意义上的"退出"。 (即终止)我的意思是"回到应用程序启动活动启动之前打开的任何东西",如果这是有意义的:)
In Java Activity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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); } |
In Kotlin Activity:
1 2 3 4 5 6 7 8 9 10 11 12 | 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) } |
我认为这个处理程序有助于在2秒后重置变量。
Sudheesh B Nair在这个问题上有一个很好的(并且被接受的)答案,我认为应该有一个更好的选择,例如;
测量时间过去并检查自上次反压后是否超过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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(); } |
回到接受的答案批评;使用
为了删除
以下示例是演示;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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); } |
感谢@NSouth的贡献;为了防止在应用程序关闭后出现toast消息,
我想我最后会分享我是如何做到的,我刚刚在我的活动中加入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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(); } |
它完全符合我的要求。包括恢复活动时的状态重置。
流程图:
Java代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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; } |
所有这些答案中都有最简单的方法。
只需在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
您需要在活动中将
根据正确的答案和评论中的建议,我创建了一个完全正常的演示,并在使用后删除处理程序回调。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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); } } } |
我希望它会有所帮助!!
我使用snackbar的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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(); } } |
简约时尚。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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); |
声明变量
Paste this in your Main Activity and this will solve your issue
退出应用程序时使用Runnable不是一个好主意,我最近想出了一种更简单的方法来记录和比较两个BACK按钮点击之间的时间。示例代码如下:
1 2 3 4 5 6 7 8 9 10 | 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(); } |
这样就可以通过双重BACK按钮在一定的延迟时间内点击退出应用程序,该延迟时间为2000毫秒。
接受的答案是最佳答案,但如果您使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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); } |
exitToast = Toast.makeText(getApplicationContext(),"再按一次退出",Toast.LENGTH_SHORT);
最后创建一个onBackPressedMethod作为Follows:
1 2 3 4 5 6 7 8 9 10 | @Override public void onBackPressed() { if (exitToast.getView().isShown()) { exitToast.cancel(); finish(); } else { exitToast.show(); } } |
这个工作正常,我已经测试过。我认为这更简单。
它不是内置功能。我认为这甚至不是推荐的行为。 Android应用无意退出:
为什么Android应用程序不提供"退出"选项?
Zefnus使用System.currentTimeMillis()的答案是最好的(+1)。我这样做的方式并不比这更好,但仍然发布它以增加上述想法。
如果按下后退按钮时看不到吐司,则显示吐司,而如果可见(背面已在最后
1 2 3 4 5 6 7 8 9 10 11 12 | exitToast = Toast.makeText(this,"Press again to exit", Toast.LENGTH_SHORT); . . @Override public void onBackPressed() { if (exitToast.getView().getWindowToken() == null) //if toast is currently not visible exitToast.show(); //then show toast saying 'press againt to exit' else { //if toast is visible then finish(); //or super.onBackPressed(); exitToast.cancel(); } } |
在java中
1 2 3 4 5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @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
1 2 3 4 5 | private var exit = false if (exit) { onBackPressed() } |
1 2 3 4 5 6 7 8 9 10 11 | 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) } } |
最近,我需要在我的应用程序中实现这个后退按钮功能。原始问题的答案很有用,但我还要考虑两点:
根据答案和评论,我创建了以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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(); } } } } |
上面的代码假定使用了支持库。如果使用片段但不使用支持库,则需要将
如果永远不会取消后退按钮,请删除第一个
此外,重要的是要注意自Android 2.0以来支持
1 2 3 4 5 6 7 8 9 10 11 12 | @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); } |
我知道这是一个非常古老的问题,但这是做你想做的最简单的方法。
1 2 3 4 5 6 7 8 9 10 11 | @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(); } } |
我知道这不是最好的方法,但它工作正常!
为此,我实现了以下功能:
1 2 3 4 5 6 7 8 9 10 | 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(); } |
当您将先前的堆栈活动存储在堆栈中时,这也会有所帮助。
我修改了Sudheesh的答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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); } |
1 2 3 4 5 6 7 8 | @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); } |
这是完整的工作代码。并且不要忘记删除回调,以免它在应用程序中导致内存泄漏。 :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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); } } |
当HomeActivity包含导航抽屉和双backPressed()功能退出应用程序时。
(不要忘记初始化全局变量boolean doubleBackToExitPressedOnce = false;)
2秒后新的处理程序将doubleBackPressedOnce变量设置为false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @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); } } } |
在这里,我已经概括地编写了N个抽头计数的代码。该代码类似于Android设备手机中的Enable Developer选项编写。即使您可以在开发人员测试应用程序时使用此功能来启用功能。
1 2 3 4 5 6 7 8 9 10 | private Handler tapHandler; private Runnable tapRunnable; private int mTapCount = 0; private int milSecDealy = 2000; onCreate(){ ... tapHandler = new Handler(Looper.getMainLooper()); } |
在backpress或logout选项上调用askToExit()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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(); } |
这与已接受和最多投票的回复相同,但是这个剪辑使用了Snackbar而不是Toast。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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); } |
我通常会添加评论,但我的声誉不允许这样做。
所以这是我的两分钱:
在Kotlin中,您可以使用协同程序将设置延迟为false:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 } } |
你必须导入:
1 2 3 | import kotlinx.coroutines.launch import kotlinx.coroutines.delay import kotlinx.coroutines.GlobalScope |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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); } |
这是另一种方法......使用CountDownTimer方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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(); } } |
我用这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import android.app.Activity; import android.support.annotation.StringRes; import android.widget.Toast; public class ExitApp { private static long lastClickTime; public static void now(Activity ctx, @StringRes int message) { now(ctx, ctx.getString(message), 2500); } public static void now(Activity ctx, @StringRes int message, long time) { now(ctx, ctx.getString(message), time); } public static void now(Activity ctx, String message, long time) { if (ctx != null && !message.isEmpty() && time != 0) { if (lastClickTime + time > System.currentTimeMillis()) { ctx.finish(); } else { Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show(); lastClickTime = System.currentTimeMillis(); } } } } |
在事件
1 2 3 4 | @Override public void onBackPressed() { ExitApp.now(this,"Press again for close"); } |
或
for change需要close,指定的毫秒数
在Sudheesh B Nair的答案中有一些改进,我注意到它会等待处理程序,即使在立即按下两次,所以取消处理程序,如下所示。我也有tocled toast以防止它在app退出后显示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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); } |
我认为比Zefnus稍微好一点的方法。只调用System.currentTimeMillis()一次并省略
1 2 3 4 5 6 7 8 9 10 11 12 | 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(); } } |
对于具有导航抽屉的活动,请对OnBackPressed()使用以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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(); } } } |
就我而言,我依靠
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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(); } } |
在这种情况下,Snackbar是更好的选择,然后Toast显示退出操作。以下是使用snackbar的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @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); } |
Toast的最佳解决方案
In Java
1 2 3 4 5 6 7 8 9 10 11 12 | 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(); } } |
In Kotlin
1 2 3 4 5 6 7 8 9 10 11 | 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() } } |
按下按钮2次后返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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); } } |
以下是使用RxJava执行此操作的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
这是我对此的看法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 } } |
在Kotlin的背面按退出应用程序,您可以使用:
定义一个全局变量:
1 | private var doubleBackToExitPressedOnce = false |
覆盖onBackPressed:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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(); } } |
您还可以使用Toast的可见性,因此您不需要Handler / postDelayed超解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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(); } |
你甚至可以让它变得更简单,而且不使用手枪,只做这个=)
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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(); } } |
在不得不多次实现相同的事情之后,决定它的时间有人建立一个简单易用的库。那是
要开始,首先将
1 2 3 | dependencies { implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1' } |
接下来,在
1 2 | DoubleBackPress doubleBackPress = new DoubleBackPress(); doubleBackPress.setDoublePressDuration(3000); // msec |
然后创建一个需要在First Back Press上显示的
1 2 | FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this); doubleBackPress.setFirstBackPressAction(firstBackPressAction); // set the action |
现在,定义第二次背压发生时会发生什么。在这里,我们正在关闭活动。
1 2 3 4 5 6 7 | DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() { @Override public void actionCall() { finish(); System.exit(0); } }; |
最后,使用
1 2 3 4 | @Override public void onBackPressed() { doubleBackPress.onBackPressed(); } |
具有类似行为要求的示例GIF
我认为这就是你所需要的,我的意思是当我们想要展示这个toast时,当堆栈中只有一个活动并且用户从堆栈的最后一个活动回来时。
1 | var exitOpened=false // Declare it globaly |
并在
1 2 3 4 5 6 7 8 9 | override fun onBackPressed() { if (isTaskRoot && !exitOpened) { exitOpened=true toast("Please press back again to exit") return } super.onBackPressed() } |
这里,如果当前活动是堆栈的根活动(第一个活动),则
你可以在这里查看官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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(); } |