Bagaimana cara menampilkan dialog untuk mengonfirmasi bahwa pengguna ingin keluar dari Aktivitas Android?

274

Saya sudah mencoba menunjukkan "Anda ingin keluar?" jenis dialog ketika pengguna mencoba untuk keluar dari suatu Aktivitas.

Namun saya tidak dapat menemukan kait API yang sesuai. Activity.onUserLeaveHint()awalnya terlihat menjanjikan, tetapi saya tidak dapat menemukan cara untuk menghentikan Kegiatan dari penyelesaian.

Peter A
sumber
39
Apakah sangat penting bahwa Anda memiliki prompt ini? Ketika pengguna ingin menyelesaikan suatu Kegiatan, mereka harus dapat melakukannya segera. Anda mungkin ingin memikirkan kembali strategi Anda.
Tom R
4
Menampilkan opsi konfirmasi keluar adalah wajib untuk mendaftar di App store Samsung. Salah satu Aplikasi saya ditolak karena tidak memiliki ini.
John Ashmore
6
Itu menjengkelkan, @Samsung.
dokkaebi
3
Itu tergantung pada apa yang ingin Anda lakukan saat keluar. Jika keadaan dipertahankan dan Anda bisa menavigasi kembali, menunjukkan dialog mungkin tidak diperlukan. Namun, di salah satu aplikasi saya, saya membersihkan cookie, data, dan menutup koneksi untuk selamanya dengan komit data terakhir. Pengguna harus dibuat sadar akan finalitas pilihan mereka, terutama karena saat ini tidak umum untuk memiliki rasa finalitas dalam aplikasi mobile.
Eric
15
@ Tom R: Sama sekali tidak setuju. Ada beberapa aplikasi yang Anda tidak ingin selesaikan secara tidak sengaja. Mereka bekerja di lingkungan bisnis dan sebagainya.
TomeeNS

Jawaban:

390

Di Android 2.0+ ini akan terlihat seperti:

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

Pada versi sebelumnya akan terlihat seperti:

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

}
Jax
sumber
15
Juga di 2.0 dan di atas ada acara onBackPressed baru yang direkomendasikan lebih dari pada pengembangKeyDown.android.com/intl/zh-TW/reference/android/app/… Ada bagian di sini berbicara tentang perubahan dan pendekatan baru yang direkomendasikan. developer.android.com/intl/zh-TW/sdk/android-2.0.html
Patrick Kafka
3
Posting blog tentang menangkap tombol kembali di sini: android-developers.blogspot.com/2009/12/... Perhatikan bahwa ini tidak memungkinkan Anda untuk menangkap cara lain pengguna dapat meninggalkan aplikasi Anda: menekan rumah, memilih notifikasi, menerima telepon panggilan, dll.
hackbod
Ini berfungsi dengan baik tetapi bagaimana Anda memaksa eksekusi kode untuk berhenti saat sedang ditampilkan kepada pengguna?
anon58192932
menemukannya, ini adalah solusi hebat di sini: stackoverflow.com/questions/4381296/…
anon58192932
1
Ini adalah metode () yang saya cari tetapi saya tidak tahu harus memanggil metode mana ().
user2841300
186
@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();
}
Chanakya Vadla
sumber
5
Sebuah komentar dibuat oleh elBradford: Memanggil super onBackPressed lebih baik daripada menganggap onBackPressed hanya akan memanggil finish (). Bahkan jika itu benar sekarang, itu mungkin tidak benar di API masa depanCustomTabActivity.super.onBackPressed
mplungjan
@mplungjan Bisakah Anda mengklarifikasi komentar Anda ... Apakah Anda mengatakan lebih baik mengganti finish()kodenya super.onBackPressed()?
larangan geoengineering
Komentar berumur 3 tahun. Saya tidak tahu apa praktik yang baik di 2015
mplungjan
@mplungjan Komentar Anda merujuk ke API di masa depan, tetapi akan sangat membantu jika Anda tetap bisa menjelaskan.
larangan geoengineering
Tidak masalah. Yah, saya baru saja mencoba MyActivity.super.onBackPressed();dan berfungsi dengan baik untuk saya. Tampaknya pendekatan yang paling logis juga - untuk memanggil metode yang Anda timpa jika Anda ingin perilaku standar ketika pengguna mengetuk "Tidak."
geoengineering larangan
33

Telah memodifikasi kode @ user919216 .. dan membuatnya kompatibel dengan 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();
    }

}
suraj jain
sumber
22

Saya lebih suka keluar dengan ketuk dua kali pada tombol kembali daripada dengan Dialog keluar.

Dalam solusi ini, ia menunjukkan bersulang ketika kembali untuk pertama kalinya, memperingatkan bahwa tekan kembali akan menutup Aplikasi. Dalam contoh ini kurang dari 4 detik.

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

Token dari: http://www.androiduipatterns.com/2011/03/back-button-behavior.html

Toni Gamez
sumber
Yang ini pasti favorit saya karena Dialogbox bisa merepotkan. Saya mengubahnya sedikit untuk membuatnya 3 detik dan sepertinya sedikit lebih alami dengan spidol itu. Terima kasih untuk kirimannya.
PGMacDesign
pada double back press, idealnya aplikasi harus saya keluar tetapi dalam kode saya itu membuka Aktivitas login (berarti kembali aktivitas dengan pemintal yang diaktifkan)
techDigi
21

Jika Anda tidak yakin apakah panggilan untuk "kembali" akan keluar dari aplikasi, atau akan membawa pengguna ke aktivitas lain, Anda dapat membungkus jawaban di atas dalam tanda centang, isTaskRoot (). Ini dapat terjadi jika aktivitas utama Anda dapat ditambahkan ke tumpukan belakang beberapa kali, atau jika Anda memanipulasi riwayat tumpukan belakang Anda.

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

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

Anda juga perlu mengatur bahasa level untuk mendukung java 8 di gradle.build Anda:

compileOptions {
       targetCompatibility 1.8
       sourceCompatibility 1.8
}
vasiljevski
sumber
5

di Cina, sebagian besar Aplikasi akan mengonfirmasi keluar dengan "klik dua kali":

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);
} 
Siwei Shen 申思维
sumber
5

Pertama-tama hapus super.onBackPressed();dari onbackPressed()metode daripada dan di bawah kode:

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

}
Anjali-Systematix
sumber
2

Saya suka pendekatan @GLee dan menggunakannya dengan fragmen seperti di bawah ini.

@Override
public void onBackPressed() {
    if(isTaskRoot()) {
        new ExitDialogFragment().show(getSupportFragmentManager(), null);
    } else {
        super.onBackPressed();
    }
}

Dialog menggunakan Fragmen:

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();
    }
}
marioosh
sumber
2
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();
                }
            }
        }
    }
Mohit Hooda
sumber
y kegiatan pertama, saya tidak bisa memasukkannya ke dalam aktivitas di tengah. karena sekarang ini hanya akan menutup aktivitas saat ini dan itu menunjukkan yang sebelumnya
shareef
1

Alternatif lain adalah menampilkan a Toast/ Snackbarpada pers belakang pertama yang meminta untuk menekan kembali ke Exit , yang jauh lebih tidak mengganggu daripada menunjukkan a AlertDialoguntuk mengonfirmasi jika pengguna ingin keluar dari aplikasi.

Anda dapat menggunakan DoubleBackPress Android Libraryuntuk mencapai ini dengan beberapa baris kode. Contoh GIF yang menunjukkan perilaku serupa.

Untuk memulainya, tambahkan ketergantungan ke aplikasi Anda:

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

Selanjutnya, dalam Aktivitas Anda, terapkan perilaku yang diperlukan.

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

Akhirnya, atur ini sebagai perilaku di tekan kembali.

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