单击两次后退按钮以退出活动
Posted
技术标签:
【中文标题】单击两次后退按钮以退出活动【英文标题】:Clicking the back button twice to exit an activity 【发布时间】:2012-01-15 21:05:13 【问题描述】:我最近在很多 android 应用和游戏中都注意到了这种模式:当单击返回按钮“退出”应用程序时,Toast
会出现类似于“请再次单击返回退出”的消息.
我想知道,随着我越来越频繁地看到它,这是您可以在活动中以某种方式访问的内置功能吗?我查看了许多类的源代码,但似乎找不到任何相关内容。
当然,我可以考虑几种方法来很容易地实现相同的功能(最简单的可能是在活动中保留一个布尔值,指示用户是否已经点击过一次......)但我想知道是否有东西已经在这里了。
编辑:正如@LAS_VEGAS 所提到的,我的意思并不是传统意义上的“退出”。 (即终止)我的意思是“回到应用程序启动活动启动之前打开的任何内容”,如果这有意义的话:)
【问题讨论】:
[Android - 使用 toast 确认应用退出] [1]: ***.com/questions/14006461/… 我在使用 HoloEverywhere 库时遇到了同样的问题,您可以简单地将 android:launchMode="singleTask" 添加到清单文件中的活动定义中。 其他解决方案***.com/questions/8430805/… clicking on the android back button twice to exit the app的可能重复 【参考方案1】:这是另一种方式...使用 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();
【讨论】:
【参考方案2】:在这种情况下,Snackbar 是比 Toast 更好的选择来显示退出操作。这是使用小吃店的方法。
@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);
【讨论】:
【参考方案3】:在 Kotlin 的背面按下退出应用程序,您可以使用:
定义一个全局变量:
private var doubleBackToExitPressedOnce = false
覆盖 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)
【讨论】:
【参考方案4】:Toast 的最佳解决方案
在 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()
【讨论】:
同my answer,只是晚了5年。也许您想对我的回答进行投票和评论? :)【参考方案5】:此解决方案的独特之处在于其行为;因为非双击将显示吐司,而成功的双击将在关闭应用程序时不显示吐司。 唯一的缺点是 toast 的显示会有 650 毫秒的延迟。我相信这是具有最佳行为的最佳解决方案,因为逻辑表明,如果没有这样的延迟,就不可能有这种行为
//App Closing Vars
private var doubleBackPressedInterval: Long = 650
private var doubleTap = false
private var pressCount = 0
private var timeLimit: Long = 0
override fun onBackPressed()
pressCount++
if(pressCount == 1)
timeLimit = System.currentTimeMillis() + doubleBackPressedInterval
if(!doubleTap)
showExitInstructions()
if(pressCount == 2)
if(timeLimit > System.currentTimeMillis())
doubleTap = true
super.onBackPressed()
else
showExitInstructions()
pressCount = 1
timeLimit = System.currentTimeMillis() + doubleBackPressedInterval
private fun showExitInstructions()
Handler().postDelayed(
if(!doubleTap)
Toast.makeText(this, "Try Agian", Toast.LENGTH_SHORT).show()
, doubleBackPressedInterval)
【讨论】:
【参考方案6】:This 答案很容易使用,但我们需要双击退出。我只是修改答案,
@Override
public void onBackPressed()
++k;
if(k==1)
Toast.makeText(this, "Press back one more time to exit", Toast.LENGTH_SHORT).show();
new Handler(Looper.getMainLooper()).postDelayed(new Runnable()
@Override
public void run()
--k;
,1000);
else
//do whatever you want to do on the click after the first for example:
finishAffinity();
【讨论】:
【参考方案7】:在不得不多次实现相同的事情之后,决定是时候构建一个简单易用的库了。那是DoubleBackPress Android library
。 README
解释了与示例一起提供的所有 API(如 ToastDisplay + Exit Activity),但这里只是简短的步骤。
首先,将dependency
添加到您的应用程序中:
dependencies
implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1'
接下来,在您的 Activity
中创建一个 DoubleBackPress
对象,该对象提供所需的行为。
DoubleBackPress doubleBackPress = new DoubleBackPress();
doubleBackPress.setDoublePressDuration(3000); // msec
然后创建一个Toast
,该Toast
需要在First Back Press 时显示。在这里,您可以创建自己的Toast
,或使用library
中提供的Standard Toast
。通过后一个选项在此处执行此操作。
FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);
doubleBackPress.setFirstBackPressAction(firstBackPressAction); // set the action
现在,定义第二次背压发生时应该发生的情况。在这里,我们正在关闭 Activity。
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction()
@Override
public void actionCall()
finish();
System.exit(0);
;
最后,用DoubleBackPress
行为覆盖您的后按行为。
@Override
public void onBackPressed()
doubleBackPress.onBackPressed();
Example GIF of similar behavioural requirements
【讨论】:
【参考方案8】: 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();
【讨论】:
【参考方案9】:你甚至可以让它更简单,不使用hander,只做这个=)
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();
【讨论】:
【参考方案10】:您还可以使用 Toast 的可见性,因此您不需要那个 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();
【讨论】:
【参考方案11】: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();
【讨论】:
【参考方案12】:这是我的看法:
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
【讨论】:
我试试这个我猜这是无泄漏的解决方案。【参考方案13】:这是使用 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)
【讨论】:
【参考方案14】:按钮按下 2 次后返回
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);
【讨论】:
【参考方案15】:我认为这就是你所需要的,我的意思是当我们想要显示这个 toast 时,堆栈中只有一个活动并且用户从堆栈的最后一个活动按回。 p>
var exitOpened=false // Declare it globaly
并在onBackPressed
方法中将其更改为:
override fun onBackPressed()
if (isTaskRoot && !exitOpened)
exitOpened=true
toast("Please press back again to exit")
return
super.onBackPressed()
这里,如果当前活动是堆栈的根活动(第一个活动),isTaskRoot
将返回 true,否则返回 false。
可以查看官方文档here
【讨论】:
【参考方案16】:我已经尝试为此创建一个 utils 类,因此任何活动或片段都可以更简单地实现它。
代码是用 Kotlin 编写的,并且还具有 Java 互操作性。
我正在使用协程来延迟和重置标志变量。但您可以根据需要对其进行修改。
其他文件:SafeToast.kt
lateinit var toast: Toast
fun Context.safeToast(msg: String, length: Int = Toast.LENGTH_LONG, action: (Context) -> Toast = default)
toast = SafeToast.makeText(this@safeToast, msg, length).apply
// do anything new here
action(this@safeToast)
show()
fun Context.toastSpammable(msg: String)
cancel()
safeToast(msg, Toast.LENGTH_SHORT)
fun Fragment.toastSpammable(msg: String)
cancel()
requireContext().safeToast(msg, Toast.LENGTH_SHORT)
private val default: (Context) -> Toast = it -> SafeToast.makeText(it, "", Toast.LENGTH_LONG)
private fun cancel()
if (::toast.isInitialized) toast.cancel()
ActivityUtils.kt
@file:JvmMultifileClass
@file:JvmName("ActivityUtils")
package your.company.com
import android.app.Activity
import your.company.com.R
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
private var backButtonPressedTwice = false
fun Activity.onBackPressedTwiceFinish()
onBackPressedTwiceFinish(getString(R.string.msg_back_pressed_to_exit), 2000)
fun Activity.onBackPressedTwiceFinish(@StringRes message: Int, time: Long)
onBackPressedTwiceFinish(getString(message), time)
fun Activity.onBackPressedTwiceFinish(message: String, time: Long)
if (backButtonPressedTwice)
onBackPressed()
else
backButtonPressedTwice = true
toastSpammable(message)
GlobalScope.launch
delay(time)
backButtonPressedTwice = false
在 Kotlin 中的使用
// ActivityA.kt
override fun onBackPressed()
onBackPressedTwiceFinish()
在 Java 中的使用
@Override
public void onBackPressed()
ActivityUtils.onBackPressedTwiceFinish()
这段代码的灵感来自@webserveis here
【讨论】:
以上是关于单击两次后退按钮以退出活动的主要内容,如果未能解决你的问题,请参考以下文章
如何处理后退按钮android以退出应用程序并在首页中打开时关闭本机导航侧菜单
如何在主页中打开后退按钮 android 以退出应用程序并关闭反应本机导航侧菜单
在android qtquick中单击后退按钮时应用程序退出