最近我在许多Android应用和游戏中注意到这种模式:当点击后退按钮“退出”应用时,Toast会出现类似于“请再次点击后退退出”的消息。

我在想,当我越来越频繁地看到它时,这是一个内置的功能,你可以在某个活动中访问它吗?我已经看了很多类的源代码,但我似乎找不到任何关于这一点。

当然,我可以想到一些很容易实现相同功能的方法(最简单的可能是在活动中保留一个布尔值,指示用户是否已经单击过一次…),但我想知道这里是否已经有一些东西。

编辑:正如@LAS_VEGAS所提到的,我并不是指传统意义上的“退出”。(即终止)我的意思是“回到应用程序启动活动启动之前打开的任何东西”,如果这有意义的话:)


当前回答

这个解的独特之处在于它的行为;其中,非双击将显示吐司和成功双击将显示没有吐司,同时关闭应用程序。 唯一的缺点是吐司的显示将有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)
}

其他回答

在我的例子中,我依赖snackbar# isshows()来获得更好的用户体验。

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();
    }
}

我通常会加一条评论,但我的声誉不允许这样做。 下面是我的观点:

在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

以下是我的看法:

 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
     }
 }

大多数现代应用程序只使用一个活动和多个片段。所以如果你在使用导航组件并且需要从home片段调用实现,这是解决方案。

override fun onAttach(context: Context) {
    super.onAttach(context)
    val callback: OnBackPressedCallback = object :
    OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            if (doubleBackPressed) {
                activity.finishAffinity()
            }
            doubleBackPressed = true
            Toast.makeText(requireActivity(), "Press BACK again to exit", Toast.LENGTH_LONG).show()
            Handler(Looper.myLooper()!!).postDelayed(Runnable {doubleBackPressed = false},
                2000)
            }
        }
    requireActivity().onBackPressedDispatcher.addCallback(this, callback)
}

我用这个

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(这个,R.string.double_back_pressed)

对于需要关闭的更改秒,指定毫秒

ExitApp.now (R.string.double_back_pressed, 5000)