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

Posted

技术标签:

【中文标题】如何显示对话框以确认用户希望退出 Android 活动?【英文标题】:How to show a dialog to confirm that the user wishes to exit an Android Activity? 【发布时间】:2011-01-16 12:13:39 【问题描述】:

我一直在尝试显示“你想退出吗?”用户尝试退出 Activity 时的对话框类型。

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

【问题讨论】:

你有这个提示是绝对必要的吗?当用户想要完成一个活动时,他们应该能够立即完成。您可能需要重新考虑您的策略。 显示退出确认选项对于在三星应用商店上市是强制性的。我的一个应用因为没有这个而被拒绝。 这太令人讨厌了,@Samsung。 这取决于你想在退出时做什么。如果状态被保留并且您可以返回导航,则可能不需要显示对话框。然而,在我的一个应用程序中,我清理了 cookie、数据,并在最终提交数据时永久关闭连接。应该让用户意识到他们选择的最终确定性,特别是因为如今在移动应用程序中很少有这种确定性。 @Tom R:完全不同意。有些应用程序您不想意外完成。他们在商业环境中工作等等。 【参考方案1】:

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


【讨论】:

同样在 2.0 及更高版本中,有一个新的 onBackPressed 事件被推荐而不是 onKeyDown developer.android.com/intl/zh-TW/reference/android/app/… 这里有一个部分讨论了变化和新的推荐方法。 developer.android.com/intl/zh-TW/sdk/android-2.0.html 关于在此处捕获返回键的博文:android-developers.blogspot.com/2009/12/… 请注意,这不允许您捕获用户离开应用的其他方式:按主页、选择通知、接听电话、等 这很好用,但是如何在向用户显示代码时强制停止执行代码? 找到了,这是一个很好的解决方案:***.com/questions/4381296/… 这是我正在寻找的方法(),但我不知道在哪里调用这个方法()。【参考方案2】:
@Override
public void onBackPressed() 
    new AlertDialog.Builder(this)
           .setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() 
               public void onClick(DialogInterface dialog, int id) 
                   ExampleActivity.super.onBackPressed();
               
           )
           .setNegativeButton("No", null)
           .show();

【讨论】:

elBradford 发表了评论:调用超级 onBackPressed 比假设 onBackPressed 只会调用 finish() 更好。即使现在是这样,但在未来的 API 中可能不是这样CustomTabActivity.super.onBackPressed @mplungjan 您能否澄清您的评论...您是说用super.onBackPressed() 替换finish() 代码更好吗? 评论已有 3 年历史。我不知道 2015 年有什么好的做法 @mplungjan 您的评论提到了未来的 API,但如果您能澄清一下,将会很有帮助。 没有问题。好吧,我刚刚尝试过MyActivity.super.onBackPressed();,它对我来说很好用。这似乎也是最合乎逻辑的方法 - 如果您想要用户点击“否”时的标准行为,则调用您要覆盖的方法。【参考方案3】:

已修改@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();
    


【讨论】:

【参考方案4】:

比起退出对话框,我更喜欢双击返回按钮退出。

在这个解决方案中,第一次返回时它会显示一个 toast,警告再次返回将关闭应用程序。在本例中不到 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();
 

令牌来自:http://www.androiduipatterns.com/2011/03/back-button-behavior.html

【讨论】:

这绝对是我的最爱,因为对话框可能很麻烦。我稍微改变了一下,让它变成 3 秒,用那个标记看起来更自然一些。感谢您的帖子。 在理想情况下双击应用程序应该退出但在我的代码中它打开了一个登录活动(意味着启用了微调器的返回活动)【参考方案5】:

如果您不确定对“返回”的调用是否会退出应用程序,或者是否会将用户带到另一个活动,您可以将上述答案包含在检查中,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();

【讨论】:

完全搜索这个。谢谢..我认为这必须标记为答案。其他都没用。我正在寻找 isTaskRoot() 方法的功能。【参考方案6】:

在中国,大部分App都会通过“点击两次”确认退出:

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

【讨论】:

【参考方案7】:

首先从onbackPressed()方法中删除super.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();


【讨论】:

【参考方案8】:

使用 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

【讨论】:

【参考方案9】:
Just put this code in your first activity 

@Override
    public void onBackPressed() 
        if (drawerLayout.isDrawerOpen(GravityCompat.END)) 
            drawerLayout.closeDrawer(GravityCompat.END);
        
        else 
// if your using fragment then you can do this way
            int fragments = getSupportFragmentManager().getBackStackEntryCount();
            if (fragments == 1) 
new AlertDialog.Builder(this)
           .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", null)
           .show();


             else 
                if (getFragmentManager().getBackStackEntryCount() > 1) 
                    getFragmentManager().popBackStack();
                 else 

           super.onBackPressed();
                
            
        
    

【讨论】:

第一个活动,我不能把它放在中间的活动中。因为现在它会关闭当前活动并显示上一个活动【参考方案10】:

我喜欢@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();
    

【讨论】:

【参考方案11】:

另一种选择是在第一次后按时显示Toast/Snackbar,要求再次按返回退出,这比显示AlertDialog 要少得多确认用户是否要退出应用。

您可以使用DoubleBackPress Android Library 通过几行代码来实现此目的。 Example GIF showing similar behaviour.

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

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


接下来,在您的 Activity 中,实现所需的行为。

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

【讨论】:

以上是关于如何显示对话框以确认用户希望退出 Android 活动?的主要内容,如果未能解决你的问题,请参考以下文章

android dialog怎么关闭

Android:如何在 PIP 模式下显示 AlertDialog?

单击 <a> 链接时如何显示确认对话框?

如何在 Flutter 中显示 2 个连续的对话框

winform中如何使用确认对话框

如何在android中显示位置设置对话框?