[java] 활동을 종료하려면 뒤로 단추를 두 번 클릭하십시오.

최근 많은 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 년 말) 밀리 초 세트 – 리셋 경유 HandlerpostDelayed()방법은 내 마음에 와서 제일 먼저했다. 그러나 postDelayed()활동이 닫히면 작업을 취소하여을 (를) 제거해야합니다 Runnable.

을 제거하려면 익명Runnable 으로 선언해서는 안되며 또한 멤버와 함께 선언 해야합니다 . 그러면의 방법을 적절히 호출 할 수 있습니다.HandlerremoveCallbacks()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);
        }
    }

}

도움이 되길 바랍니다!