单击两次后退按钮以退出活动

Posted

技术标签:

【中文标题】单击两次后退按钮以退出活动【英文标题】:Clicking the back button twice to exit an activity 【发布时间】:2012-01-15 21:05:13 【问题描述】:

我最近在很多 android 应用和游戏中都注意到了这种模式:当单击返回按钮“退出”应用程序时,Toast 会出现类似于“请再次单击返回退出”的消息.

我想知道,随着我越来越频繁地看到它,这是您可以在活动中以某种方式访问​​的内置功能吗?我查看了许多类的源代码,但似乎找不到任何相关内容。

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

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

【问题讨论】:

[Android - 使用 toast 确认应用退出] [1]: ***.com/questions/14006461/… 我在使用 HoloEverywhere 库时遇到了同样的问题,您可以简单地将 android:launchMode="singleTask" 添加到清单文件中的活动定义中。 其他解决方案***.com/questions/8430805/… clicking on the android back button twice to exit the app的可能重复 【参考方案1】:

这是另一种方式...使用 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();
        

    

【讨论】:

【参考方案2】:

在这种情况下,Snackbar 是比 Toast 更好的选择来显示退出操作。这是使用小吃店的方法。

@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);
        

【讨论】:

【参考方案3】:

在 Kotlin 的背面按下退出应用程序,您可以使用:

定义一个全局变量:

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)
    

【讨论】:

【参考方案4】:

Toast 的最佳解决方案

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

在 Kotlin 中

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

【讨论】:

同my answer,只是晚了5年。也许您想对我的回答进行投票和评论? :)【参考方案5】:

此解决方案的独特之处在于其行为;因为非双击将显示吐司,而成功的双击将在关闭应用程序时不显示吐司。 唯一的缺点是 toast 的显示会有 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)

【讨论】:

【参考方案6】:

This 答案很容易使用,但我们需要双击退出。我只是修改答案,

    @Override
public void onBackPressed() 
    ++k;
    if(k==1)
        Toast.makeText(this, "Press back one more time to exit", Toast.LENGTH_SHORT).show();
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() 
            @Override
            public void run() 
                --k;
            
        ,1000);
    else
        //do whatever you want to do on the click after the first for example:
        finishAffinity();
    

【讨论】:

【参考方案7】:

在不得不多次实现相同的事情之后,决定是时候构建一个简单易用的库了。那是DoubleBackPress Android libraryREADME 解释了与示例一起提供的所有 API(如 ToastDisplay + Exit Activity),但这里只是简短的步骤。


首先,将dependency 添加到您的应用程序中:

dependencies 
    implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1'
 

接下来,在您的 Activity 中创建一个 DoubleBackPress 对象,该对象提供所需的行为。

DoubleBackPress doubleBackPress = new DoubleBackPress();
doubleBackPress.setDoublePressDuration(3000);           // msec

然后创建一个Toast,该Toast 需要在First Back Press 时显示。在这里,您可以创建自己的Toast,或使用library 中提供的Standard Toast。通过后一个选项在此处执行此操作。

FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);
doubleBackPress.setFirstBackPressAction(firstBackPressAction);   // set the action

现在,定义第二次背压发生时应该发生的情况。在这里,我们正在关闭 Activity。

DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() 
    @Override
    public void actionCall() 
        finish();
        System.exit(0);
    
;

最后,用DoubleBackPress 行为覆盖您的后按行为。

@Override
public void onBackPressed() 
    doubleBackPress.onBackPressed();

Example GIF of similar behavioural requirements

【讨论】:

【参考方案8】:
 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();
    

【讨论】:

【参考方案9】:

你甚至可以让它更简单,不使用hander,只做这个=)

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

【讨论】:

【参考方案10】:

您还可以使用 Toast 的可见性,因此您不需要那个 Handler/postDelayed ultra 解决方案。

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

【讨论】:

【参考方案11】:
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();

            

        

【讨论】:

【参考方案12】:

这是我的看法:

 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
     
 

【讨论】:

我试试这个我猜这是无泄漏的解决方案。【参考方案13】:

这是使用 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)

【讨论】:

【参考方案14】:

按钮按下 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);
    


【讨论】:

【参考方案15】:

我认为这就是你所需要的,我的意思是当我们想要显示这个 toast 时,堆栈中只有一个活动并且用户从堆栈的最后一个活动按回。 p>

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。

可以查看官方文档here

【讨论】:

【参考方案16】:

我已经尝试为此创建一个 utils 类,因此任何活动或片段都可以更简单地实现它。

代码是用 Kotlin 编写的,并且还具有 Java 互操作性。

我正在使用协程来延迟和重置标志变量。但您可以根据需要对其进行修改。

其他文件SafeToast.kt

lateinit var toast: Toast

fun Context.safeToast(msg: String, length: Int = Toast.LENGTH_LONG, action: (Context) -> Toast = default) 
    toast = SafeToast.makeText(this@safeToast, msg, length).apply 
        // do anything new here
        action(this@safeToast)
        show()
    


fun Context.toastSpammable(msg: String) 
    cancel()
    safeToast(msg, Toast.LENGTH_SHORT)


fun Fragment.toastSpammable(msg: String) 
    cancel()
    requireContext().safeToast(msg, Toast.LENGTH_SHORT)


private val default: (Context) -> Toast =  it -> SafeToast.makeText(it, "", Toast.LENGTH_LONG) 

private fun cancel() 
    if (::toast.isInitialized) toast.cancel()

ActivityUtils.kt

@file:JvmMultifileClass
@file:JvmName("ActivityUtils")
package your.company.com

import android.app.Activity
import your.company.com.R
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch


private var backButtonPressedTwice = false

fun Activity.onBackPressedTwiceFinish() 
    onBackPressedTwiceFinish(getString(R.string.msg_back_pressed_to_exit), 2000)


fun Activity.onBackPressedTwiceFinish(@StringRes message: Int, time: Long) 
    onBackPressedTwiceFinish(getString(message), time)


fun Activity.onBackPressedTwiceFinish(message: String, time: Long) 
    if (backButtonPressedTwice) 
        onBackPressed()
     else 
        backButtonPressedTwice = true
        toastSpammable(message)
        GlobalScope.launch 
            delay(time)
            backButtonPressedTwice = false
        
    

在 Kotlin 中的使用

// ActivityA.kt
override fun onBackPressed() 
    onBackPressedTwiceFinish()

在 Java 中的使用

@Override 
public void onBackPressed() 
    ActivityUtils.onBackPressedTwiceFinish()

这段代码的灵感来自@webserveis here

【讨论】:

以上是关于单击两次后退按钮以退出活动的主要内容,如果未能解决你的问题,请参考以下文章

禁用后退按钮,但是当点击两次退出应用程序时反应原生

如何处理后退按钮android以退出应用程序并在首页中打开时关闭本机导航侧菜单

如何在主页中打开后退按钮 android 以退出应用程序并关闭反应本机导航侧菜单

在android qtquick中单击后退按钮时应用程序退出

当后退按钮点击两次时如何让Xamarin.Android app退出(确认包含点击之间的消息)?

按下后退按钮时如何退出?