如何显示对话框以确认用户希望退出Android活动?

如何显示对话框以确认用户希望退出Android活动?,android,android-activity,android-dialog,activity-finish,Android,Android Activity,Android Dialog,Activity Finish,我一直在尝试在用户试图退出活动时显示“是否要退出?”类型的对话框 但是,我找不到合适的API挂钩Activity.onUserLeaveHint()最初看起来很有希望,但我找不到阻止活动完成的方法。在Android 2.0+中,这看起来像: @Override public void onBackPressed() { new AlertDialog.Builder(this) .setIcon(android.R.drawable.ic_dialog_alert)

我一直在尝试在用户试图退出活动时显示“是否要退出?”类型的对话框


但是,我找不到合适的API挂钩
Activity.onUserLeaveHint()
最初看起来很有希望,但我找不到阻止活动完成的方法。

在Android 2.0+中,这看起来像:

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setTitle("Closing Activity")
        .setMessage("Are you sure you want to close this activity?")
        .setPositiveButton("Yes", new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            finish();    
        }

    })
    .setNegativeButton("No", null)
    .show();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    //Handle the back button
    if(keyCode == KeyEvent.KEYCODE_BACK) {
        //Ask the user if they want to quit
        new AlertDialog.Builder(this)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setTitle(R.string.quit)
        .setMessage(R.string.really_quit)
        .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

                //Stop the activity
                YourClass.this.finish();    
            }

        })
        .setNegativeButton(R.string.no, null)
        .show();

        return true;
    }
    else {
        return super.onKeyDown(keyCode, event);
    }

}
在早期版本中,它看起来像:

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setTitle("Closing Activity")
        .setMessage("Are you sure you want to close this activity?")
        .setPositiveButton("Yes", new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            finish();    
        }

    })
    .setNegativeButton("No", null)
    .show();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    //Handle the back button
    if(keyCode == KeyEvent.KEYCODE_BACK) {
        //Ask the user if they want to quit
        new AlertDialog.Builder(this)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setTitle(R.string.quit)
        .setMessage(R.string.really_quit)
        .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

                //Stop the activity
                YourClass.this.finish();    
            }

        })
        .setNegativeButton(R.string.no, null)
        .show();

        return true;
    }
    else {
        return super.onKeyDown(keyCode, event);
    }

}

已修改@user919216代码。。并使其与WebView兼容

@Override
public void onBackPressed() {
    if (webview.canGoBack()) {
        webview.goBack();

    }
    else
    {
     AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
       .setCancelable(false)
       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                finish();
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
           }
       });
AlertDialog alert = builder.create();
alert.show();
    }

}

如果您不确定对“后退”的呼叫是否会退出应用程序,或者是否会将用户带到另一个活动,您可以将上述答案包装在一个复选框isTaskRoot()中。如果主活动可以多次添加到后台堆栈,或者如果您正在处理后台堆栈历史记录,则可能会发生这种情况

if(isTaskRoot()) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure you want to exit?")
       .setCancelable(false)
       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                YourActivity.super.onBackPressed;
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
           }
       });
    AlertDialog alert = builder.create();
    alert.show();

} else {
    super.onBackPressed();
}

我更喜欢双击后退按钮退出,而不是退出对话框

在这个解决方案中,它会在第一次返回时显示一个祝酒词,警告再次按下将关闭应用程序。在本例中,小于4秒

private Toast toast;
private long lastBackPressTime = 0;

@Override
public void onBackPressed() {
  if (this.lastBackPressTime < System.currentTimeMillis() - 4000) {
    toast = Toast.makeText(this, "Press back again to close this app", 4000);
    toast.show();
    this.lastBackPressTime = System.currentTimeMillis();
  } else {
    if (toast != null) {
    toast.cancel();
  }
  super.onBackPressed();
 }
}
私人吐司;
私人长时间lastBackPressTime=0;
@凌驾
public void onBackPressed(){
if(this.lastBackPressTime

来自的标记:

我喜欢@GLee方法,并将其与下面的片段一起使用

@Override
public void onBackPressed() {
    if(isTaskRoot()) {
        new ExitDialogFragment().show(getSupportFragmentManager(), null);
    } else {
        super.onBackPressed();
    }
}
使用片段的对话框:

public class ExitDialogFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
            .setTitle(R.string.exit_question)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    getActivity().finish();
                }
            })
            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    getDialog().cancel();
                }
            })
            .create();
    }
}
使用Lambda:

    new AlertDialog.Builder(this).setMessage(getString(R.string.exit_msg))
        .setTitle(getString(R.string.info))
        .setPositiveButton(getString(R.string.yes), (arg0, arg1) -> {
            moveTaskToBack(true);
            finish();
        })
        .setNegativeButton(getString(R.string.no), (arg0, arg1) -> {
        })
        .show();
您还需要在gradle.build中设置级别语言以支持java 8:

compileOptions {
       targetCompatibility 1.8
       sourceCompatibility 1.8
}

在中国,大多数应用程序会通过“点击两次”确认退出:

boolean doublebacktoexit pressedonce=false;
@凌驾
public void onBackPressed(){
如果(DoubleBacktoExit按Donce){
super.onBackPressed();
返回;
}
this.doublebacktoexit pressedonce=true;
Toast.makeText(这是“请再次单击返回退出”,Toast.LENGTH_SHORT.show();
new Handler().postDelayed(new Runnable()){
@凌驾
公开募捐{
DoubleBackToExit PresseDonce=false;
}
}, 2000);
} 

首先删除
super.onBackPressed()来自
onbackPressed()
方法,代码如下:

@Override
public void onBackPressed() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    MyActivity.this.finish();
               }
           })
           .setNegativeButton("No", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
               }
           });
    AlertDialog alert = builder.create();
    alert.show();

}

另一种选择是在第一次按back键时显示一个
Toast
/
Snackbar
,要求再次按back键退出,这比显示一个
AlertDialog
来确认用户是否要退出应用程序的干扰小得多

您可以使用通过几行代码来实现这一点

首先,将依赖项添加到应用程序中:

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

接下来,在您的活动中,实施所需的行为

// set the Toast to be shown on FirstBackPress (ToastDisplay - builtin template)
// can be replaced by custom action (new FirstBackPressAction{...})
FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);

// set the Action on DoubleBackPress
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() {
    @Override
    public void actionCall() {
        // TODO : Exit the application
        finish();
        System.exit(0);
    }
};

// setup DoubleBackPress behaviour : close the current Activity
DoubleBackPress doubleBackPress = new DoubleBackPress()
        .withDoublePressDuration(3000)     // msec - wait for second back press
        .withFirstBackPressAction(firstBackPressAction)
        .withDoubleBackPressAction(doubleBackPressAction);
最后,将此设置为背压时的行为

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


你有这个提示是绝对必要的吗?当用户想要完成一项活动时,他们应该能够立即完成。您可能需要重新考虑您的策略。在三星应用商店登录时,必须显示退出确认选项。我的一个应用因为没有这个被拒绝了。这很讨厌,@Samsung。这取决于你退出后想做什么。如果状态被保留,并且您可以返回,则可能不需要显示对话框。然而,在我的一个应用程序中,我最终提交了数据,从而彻底清理了cookie、数据和紧密连接。应该让用户意识到他们选择的最终性,特别是因为在今天的移动应用程序中,这种最终性的感觉并不常见。@Tom R:完全不同意。有些应用程序是你不想意外完成的。在2.0及以上版本中,还有一个新的onBackPressed事件建议使用onKeyDown。这里有一节讨论了更改和新的推荐方法。关于在此处捕获back键的博客文章:请注意,这不允许您捕获用户可以离开应用程序的其他方式:按home键、选择通知、接听电话等。这非常有效,但如何在向用户显示代码时强制停止代码执行?找到了,这是一个很好的解决方案:这是我正在寻找的方法(),但我不知道在哪里调用此方法()。elBradford发表了评论:调用超级onBackPressed比假设onBackPressed只调用finish()要好。即使现在是这样,在未来的API中也可能不是这样的
CustomTabActivity.super.onBackPressed
@mplungjan您能澄清一下您的评论吗。。。你是说最好用
super.onBackPressed()
替换
finish()。我不知道什么是好的实践2015@mplungjan你的评论提到了未来的API,但如果你能澄清一下,这将是很有帮助的。没有问题。嗯,我刚刚尝试了
MyActivity.super.onBackPressed()对我来说很好。这似乎也是最合乎逻辑的方法——当用户点击“否”时,如果您想要标准的行为,则调用您要覆盖的方法。这一方法无疑是我的最爱,因为对话框可能会很麻烦。我稍微改了一下,改为3秒,用那个记号笔看起来更自然了。感谢您的帖子。如果我退出,请按双后退按钮,但在我的代码中,它打开了一个登录活动(表示启用微调器的后退活动)y第一个活动,我不能将其放在中间的活动中。因为现在它jsut关闭了当前的活动,并显示了以前的一次搜索。非常感谢。我认为这必须被标记为答案。其他的没用。我正在搜索isTaskRoot()方法所具有的功能。