最近、多くのAndroidアプリやゲームでこのパターンに気付いた。アプリケーションを「終了」するために戻るボタンをクリックすると、Toast
に「もう一度戻るにはもう一度クリックしてください」というようなメッセージが表示されます。
私はそれがますます頻繁に見ているように、あなたがどういうわけかあなたが活動の中でアクセスすることができる組み込みの機能であるということを疑問に思いましたか?私は多くのクラスのソースコードを調べましたが、それについて何かを見つけることができないようです。
もちろん、同じ機能を非常に簡単に達成するためのいくつかの方法を考えることができます(最も簡単な方法は、ユーザーが既に1回クリックしたかどうかを示すブール値を保持することです)。 。
EDIT:@LAS_VEGASが述べたように、私は伝統的な意味で「終了」を意味しませんでした。それが理にかなっているなら、私は「アプリケーション開始アクティビティが開始される前に開いていたものに戻る」という意味でした:)
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);
}
コトリン活動中:
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 は、この質問に対していい(そして受け入れられた)答えを持っています。
経過時間を測定し、最後のバックプレスから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();
}
承認された回答に戻るcritique;最後のTIME_INTERVAL
(2000など)で押されたかどうかを示すためにflag
NAME _を使用し、set - resetを介してHandler
name__を使用するpostDelayed()
methodが私の頭に浮かんだ最初のことでした。しかし、postDelayed()
アクションはアクティビティが終了したときにキャンセルされ、Runnable
name__が削除されます。
Runnable
name__を削除するには、anonymousと宣言してはいけません。また、Handler
name__と一緒にmemberとして宣言することはできません。それからHandler
name__の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
name__をメンバーとして宣言することができ、mExitToast
name__と言うことができ、mExitToast.cancel();
justでキャンセルできます。 super.onBackPressed();
を呼び出す前に。
私は最後にそれをどのようにしたかを共有すると思ったので、私はちょうど私の活動に加えました:
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コード:
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;
}
これらすべての答えの中で最も簡単な方法があります。
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();
}
back_pressed
オブジェクトをアクティビティのlong
として定義する必要があります。
正しい答えとコメントの提案に基づいて、絶対に問題なく動作し、使用後にハンドラのコールバックを削除するデモを作成しました。
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);
}
}
}
私はそれが役に立つことを願っています!
スナックバーを使った私の解決策:
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();
}
}
シンプルでスタイリッシュ。
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を使用することはお勧めできません。最近、2回のBACKボタンクリックの間の期間を記録して比較するためのはるかに簡単な方法を見つけました。次のようなサンプルコード
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();
}
これは、サンプルで2000ミリ秒である特定の遅延期間内に2回戻るボタンをクリックすることによってアプリケーションを終了するためのトリックを行います。
受け入れられた答えは最良のものですが、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);
}
組み込みの機能ではありません。これは推奨される動作でもないと思います。 Androidアプリは終了を意図していません。
最後に以下のようにonBackPressedMethodを作成します。
@Override
public void onBackPressed() {
if (exitToast.getView().isShown()) {
exitToast.cancel();
finish();
} else {
exitToast.show();
}
}
これは正しく動作します、私はテストしました。これはずっと簡単だと思います。
最近、私はこの戻るボタン機能を私のアプリに実装する必要がありました。元の質問に対する回答は役に立ちましたが、私はもう2つの点を考慮に入れなければなりませんでした。
答えとコメントに基づいて、次のコードを作成しました。
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();
}
}
}
}
上記のコードはサポートライブラリが使用されていることを前提としています。フラグメントを使用し、サポートライブラリを使用しない場合は、getSupportFragmentManager()
をgetFragmentManager()
に置き換えます。
戻るボタンがキャンセルされない場合は、最初のif
を削除してください。フラグメントまたはフラグメントバックスタックを使用しない場合は、2番目のif
を削除してください。
また、メソッドonBackPressed
はAndroid 2.0以降でサポートされていることに注意することが重要です。詳しい説明については このページ を確認してください。バックプレス機能を古いバージョンでも機能させるには、アクティビティに次のメソッドを追加します。
@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);
}
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);
}
}
コトリン
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)
}
}
System.currentTimeMillis()を使ったZefnus の答えが最も良い方法です(+1)。私がしたやり方はそれより良くありませんが、それでも上記のアイデアに追加するためにそれを投稿します。
戻るボタンが押されたときにトーストが表示されていない場合は表示されますが、トーストが表示されている場合(最後のToast.LENGTH_SHORT
時間内にもう一度トーストが押された場合)は終了します。
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();
}
}
これは非常に古い質問ですが、これはあなたが望むことをする最も簡単な方法です。
@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();
}
}
私はこれが最善の方法ではないことを知っています、しかしそれはうまくいきます!
これは、以前のスタックアクティビティがstackに格納されているときにも役立ちます。
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);
}
ここでは、Nタップ数のコードを一般化して書きました。コードはAndroidデバイスの携帯電話の開発者を有効にするオプションのために同様に書かれています。開発者がアプリをテストしながら、これを使って機能を有効にすることもできます。
private Handler tapHandler;
private Runnable tapRunnable;
private int mTapCount = 0;
private int milSecDealy = 2000;
onCreate(){
...
tapHandler = new Handler(Looper.getMainLooper());
}
バックプレスまたはログアウトオプションでaskToExit()を呼び出します。
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);
}
この目的のために、私は以下の機能を実装しました:
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();
}
HomeActivityにナビゲーションドロワーとdouble backPressed()機能が含まれている場合はアプリを終了します。 (グローバル変数boolean doubleBackToExitPressedOnce = falseを初期化することを忘れないでください。)2秒後の新しいハンドラは、doubleBackPressedOnce変数を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);
}
}
}
これが完全に機能するコードです。また、アプリ内でメモリリークが発生しないように、コールバックを削除することを忘れないでください。 :)
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);
}
}
私は通常コメントを加えるでしょう、しかし私の評判はこれを許しません。だからここに私の2セントがあります:
Kotlinでは、コルーチンを使用して設定を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
}
}
あなたがインポートする必要があります:
import kotlinx.coroutines.launch
import kotlinx.coroutines.delay
import kotlinx.coroutines.GlobalScope
Sudheesh B Nairの答えのいくつかの改善点、私はすぐに2回押している間もハンドラーを待つことに気づいたので、下記のようにハンドラーをキャンセルします。私はそれがアプリの終了後に表示されないようにするためにトーストをcancledしました。
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);
}
この状況では、SnackbarはToastよりもquitアクションを表示するのに適したオプションです。これが機能するスナックバーを使った方法です。
@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の代わりにSnackbarを使用したものです。
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);
}
Navigation Drawer を持つアクティビティの場合、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();
}
}
}
これは別の方法です...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);
}
これを使う
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();
}
}
}
}
イベントonBackPressed
でに使用
@Override
public void onBackPressed() {
ExitApp.now(this,"Press again for close");
}
またはExitApp.now(this,R.string.double_back_pressed)
変更秒数のクローズのために必要な、指定ミリ秒
ExitApp.now(this,R.string.double_back_pressed,5000)
Zefnusよりもやや良い方法です 。 System.currentTimeMillis()を1回だけ呼び出して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();
}
}
私の場合、私はUX
をより良くするためにSnackbar#isShown()
に頼ります。
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();
}
}
アプリを終了するにはバックプレスでコトリンでは、使用することができます。
グローバル変数を定義します。
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)
}
Toastの可視性を使うこともできるので、そのHandler/postDelayedウルトラソリューションは必要ありません。
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();
}
ボタンが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);
}
}
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();
}
}
トーストのベストソリューション
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();
}
}
コトリンで
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()
}
}
これが私の考えです。
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();
}
同じことを何度も実装しなければならなかった後、誰かが簡単に使えるライブラリを作る時が来ることを決心しました。そしてそれは DoubleBackPress Android library
です。 README
は例と一緒に提供されたすべてのAPI( ToastDisplay + Exit Activity のような)を説明しますが、ここでのステップの簡単な要約です。
まず始めに、アプリケーションにdependency
を追加します。
dependencies {
implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1'
}
次に、必要な動作を提供するDoubleBackPress
内にActivity
オブジェクトを作成します。
DoubleBackPress doubleBackPress = new DoubleBackPress();
doubleBackPress.setDoublePressDuration(3000); // msec
それからFirst Back Pressに表示する必要があるToast
を作成します。ここで、あなたはあなた自身のToast
を作成するか、library
で提供されるStandard Toast
で行くことができます。これは後のオプションで行います。
FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);
doubleBackPress.setFirstBackPressAction(firstBackPressAction); // set the action
さて、あなたのセカンドバックプレスが起こったときに何が起こるべきかを定義します。ここでは、アクティビティを閉じています。
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() {
@Override
public void actionCall() {
finish();
System.exit(0);
}
};
最後に、バックプレスの動作をDoubleBackPress
の動作でオーバーライドします。
@Override
public void onBackPressed() {
doubleBackPress.onBackPressed();
}
あなたはそれをもっと簡単にすることさえできます、そして、ハンダーを使わずに、これだけをしてください=)
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();
}
}
これは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)
これはあなたが必要としていることだと思います。私たちがこのトーストを見せたいとき、 スタック内に1つのアクティビティしかない場合、ユーザーが押し戻したとき このスタックの最後のアクティビティからです。
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を返します。
公式ドキュメント はこちら で確認できます