최근 많은 Android 앱 및 게임에서이 패턴을 발견했습니다. 뒤로 버튼을 클릭하여 애플리케이션을 “종료”하면 “다시 다시 클릭하여 종료” Toast
와 유사한 메시지가 나타납니다.
점점 더 자주 볼 수 있듯이 액티비티에서 어떻게 든 액세스 할 수있는 내장 기능입니까? 많은 클래스의 소스 코드를 살펴 보았지만 그것에 대해 아무것도 찾을 수없는 것 같습니다.
물론 동일한 기능을 매우 쉽게 달성 할 수있는 몇 가지 방법에 대해 생각할 수 있습니다 (가장 쉬운 것은 사용자가 이미 한 번 클릭했는지 여부를 나타내는 활동에 부울을 유지하는 것입니다 …).하지만 이미 여기에 무언가가 있는지 궁금합니다. .
편집 : @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();
}
수락 된 답변 비평으로 돌아 가기 ; 사용 flag
이 마지막으로 누를 경우 표시하기 위해 TIME_INTERVAL
(2000 년 말) 밀리 초 세트 – 리셋 경유 Handler
의 postDelayed()
방법은 내 마음에 와서 제일 먼저했다. 그러나 postDelayed()
활동이 닫히면 작업을 취소하여을 (를) 제거해야합니다 Runnable
.
을 제거하려면 익명Runnable
으로 선언해서는 안되며 또한 멤버와 함께 선언 해야합니다 . 그러면의 방법을 적절히 호출 할 수 있습니다.Handler
removeCallbacks()
Handler
다음 샘플은 데모입니다.
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
멤버로 선언 mExitToast
할 수 있으며 호출 mExitToast.cancel();
직전에 취소 할 수 있습니다 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();
}
그리고 그것은 내가 원하는대로 정확하게 작동합니다. 활동이 재개 될 때마다 상태 재설정을 포함합니다.
답변
공정 흐름도:
자바 코드 :
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
.
답변
스낵 바를 사용하는 솔루션 :
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);
}
}
}
도움이 되길 바랍니다!