Toast
。
我想知道,随着我越来越经常看到它,这是一种内置的功能,你可以在活动中以某种方式访问它吗?我查看了许多类的源代码,但似乎没有找到任何相关信息。
当然,我可以考虑几种很容易实现相同功能的方法(最简单的可能是在活动中保留一个布尔值,指示用户是否已经点击了一次...)但我想知道是否已经有相关的功能存在。
编辑:正如@LAS_VEGAS所提到的那样,我的意思并不是传统意义上的“退出”。(即终止)我指的是“回到应用程序启动活动之前打开的内容”,如果这有意义的话 :)Toast
。
我想知道,随着我越来越经常看到它,这是一种内置的功能,你可以在活动中以某种方式访问它吗?我查看了许多类的源代码,但似乎没有找到任何相关信息。
当然,我可以考虑几种很容易实现相同功能的方法(最简单的可能是在活动中保留一个布尔值,指示用户是否已经点击了一次...)但我想知道是否已经有相关的功能存在。
编辑:正如@LAS_VEGAS所提到的那样,我的意思并不是传统意义上的“退出”。(即终止)我指的是“回到应用程序启动活动之前打开的内容”,如果这有意义的话 :)在Java Activity中:
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(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
在 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(Looper.getMainLooper()).postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000)
}
我认为这个处理程序可以在2秒后重置变量。
Sudheesh B Nair
的答案以涵盖上述建议的评论。 - Mehul JoisarSudheesh B Nair对该问题有一个不错的(并且被接受的)答案,我认为还应该有更好的替代方案,例如:
使用时间差来检测自上次按下返回键以来是否已经过了TIME_INTERVAL
毫秒(比如2000毫秒)。以下示例代码使用System.currentTimeMillis();
来存储调用onBackPressed()
时的时间。
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();
}
回到接受答案的批判;使用一个标记
来指示上次在最后TIME_INTERVAL
(比如2000)毫秒内是否有按下,并且通过Handler
的postDelayed()
方法进行设置 - 重置是我想到的第一件事。但是当活动关闭时,postDelayed()
操作应该被取消,删除Runnable
。
为了删除Runnable
,它不能被声明为匿名,必须与Handler
一起声明为成员。然后可以适当调用Handler
的removeCallbacks()
方法。
以下示例是演示;
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消息”,可以将Toast声明为成员变量 - 比如说mExitToast,并且可以在调用super.onBackPressed()之前通过mExitToast.cancel();来取消它。最终,我想分享一下我的做法,我只是在我的活动中添加了:
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();
}
它完全按照我的期望工作。包括在恢复活动时重置状态。
在所有答案中,有一种非常简单的方法。
只需在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();
}
你需要在活动(activity)中将back_pressed
对象定义为long
类型。
流程图:
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;
}
您可以使用 Snackbar 代替 Toast,这样您可以依赖它们的可见性来决定是否关闭应用程序。看看这个例子:
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();
}
}
根据正确答案和评论中的建议,我创建了一个演示,它完全正常运行并在使用后删除处理程序回调。
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);
}
}
}
希望这会有所帮助!
onBackPressed()
中移除处理程序可以解决 内存泄漏 问题吗? - Saro Taşciyan 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);
声明变量private boolean doubleBackToExitPressedOnce = false;
把这段代码复制到你的主活动中,就能解决你的问题。
在退出应用程序时使用Runnable不是一个好主意,最近我发现了一种更简单的方法来记录和比较两次“后退”按钮点击之间的时间间隔。示例代码如下:
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();
}
在示例中,通过在一定延迟期间内双击“后退”按钮,即可完成退出应用程序的操作。
接受的答案是最好的,但如果您正在使用Android Design Support Library
,那么您可以使用SnackBar
来获得更好的视图。
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);
}
private static long back_pressed; @Override public void onBackPressed() { if (back_pressed + 2000 > System.currentTimeMillis()) super.onBackPressed(); else Toast.makeText(getBaseContext(), "再按一次退出", Toast.LENGTH_SHORT).show(); back_pressed = System.currentTimeMillis(); }
这将在用户第一次按下返回按钮时显示一个Toast消息,告诉他们再按一次退出应用程序。如果用户在2秒内再次按下返回按钮,则应用程序将被销毁并退出。 - resource8218