web-dev-qa-db-ja.com

ユーザーがAndroidアクティビティを終了することを確認するためのダイアログを表示する方法は?

「終了しますか?」というメッセージを表示しようとしています。ユーザーがアクティビティを終了しようとしたときのダイアログのタイプ。

しかし、適切なAPIフックが見つかりません。 Activity.onUserLeaveHint()は最初は有望に見えましたが、アクティビティが終了しないようにする方法を見つけることができません。

265
Peter A

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

}
387
jax
@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();
}
177
Chanakya Vadla

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

}
32
suraj jain

終了ダイアログではなく、戻るボタンをダブルタップして終了したいのです。

このソリューションでは、最初に戻ったときにトーストが表示され、もう一度押すとアプリが閉じます。この例では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

22
Toni Gamez

"back"への呼び出しがアプリを終了するのか、それともユーザーを別のアクティビティに連れて行くのかわからない場合は、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();
}
20
GLee

中国では、ほとんどのアプリが「2回クリック」で終了を確認します。

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

まず、以下のコードより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();

}
5

ラムダを使う:

    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
}
5
vasiljevski
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();
                }
            }
        }
    }
2
Mohit Hooda

私は@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();
    }
}
2
marioosh

これはうまくいきます

@Override
public void onBackPressed() {
    if (mExitOnBackPress) finish();
    else {
        Toast.makeText(this, R.string.msg_confirm_exit, Toast.LENGTH_SHORT).show();
        mExitOnBackPress = true;
        new Android.os.Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mExitOnBackPress = false;
            }
        }, 2000);
    }
}
1
user3896501

もう1つの選択肢は、最初のバックプレスでToast/Snackbarを表示してExitに戻るように要求することです。ユーザーがアプリを終了するかどうかを確認するAlertDialog

数行のコードでこれを実現するには、 DoubleBackPress Android Library を使用できます。 同様の動作を示すGIFの例

はじめに、アプリケーションに依存関係を追加します。

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

アクティビティではなくフラグメントを使用している場合は、このコードをメインアクティビティに追加してください。

    private Toast toast;
    private long lastBackPressTime = 0;
    @SuppressLint("WrongConstant")
    @Override
    public void onBackPressed() {
        int fragments = getFragmentManager().getBackStackEntryCount();
        if (fragments == 0) {
            // make layout invisible since last fragment will be removed
            if (this.lastBackPressTime < System.currentTimeMillis() - 3000) {
                toast = Toast.makeText(this, "Press back again to close this app", 3000);
                toast.show();
                this.lastBackPressTime = System.currentTimeMillis();

            }else{
                if (toast != null) {
                    toast.cancel();
                }
                super.onBackPressed();
            }

        }else{
            if (toast != null) {
                toast.cancel();
            }
            super.onBackPressed();
        }
    }
0
Firefog

アプリでフラグメントを使用する場合。ここに解決策があります

@Override
        public void onBackPressed() {

            int count = getSupportFragmentManager().getBackStackEntryCount();//User that use Android library should use getFragmentManager()


            if (count == 0) {
                new AlertDialog.Builder(this)
                        .setTitle(getString(R.string.closing_app))
                        .setMessage(getString(R.string.closing_app_msg))
                        .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }

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

            }
            else {
                super.onBackPressed();
            }
        }
0
Beyaz

ユーザーがAndroidアクティビティを終了したいことを確認するためのダイアログを表示します。

以下のコードをonBackPressedオーバーライドメソッドに追加します。

@Override
        public void onBackPressed() {

                hideViews();
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);

                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Are you sure you want to exit the activity?")
                        .setCancelable(false)
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                                    finishAffinity();
                                }
                            }
                        })
                        .setNegativeButton("No", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                            }
                        });
                AlertDialog alert = builder.create();
                alert.show();

        }

お役に立てば幸いです。

0
Android Geek