Kullanıcının bir Android Etkinliğinden çıkmak istediğini onaylamak için bir iletişim kutusu nasıl gösterilir?


274

"Çıkmak istiyor musunuz?" bir Etkinlikten çıkmaya çalıştığında iletişim kutusu türü.

Ancak uygun API kancalarını bulamıyorum. Activity.onUserLeaveHint()Başlangıçta umut verici görünüyordu, ancak Faaliyetin bitmesini durdurmak için bir yol bulamıyorum.


39
Bu istemi almanız kesinlikle gerekli mi? Kullanıcı bir Etkinliği bitirmek istediğinde, bunu hemen yapabilmelidir. Stratejinizi yeniden düşünmek isteyebilirsiniz.
Tom R

4
Çıkış onay seçeneğinin görüntülenmesi, Samsung'un App store'da listelenmesi için zorunludur. Uygulamalarımdan biri buna sahip olmadığı için reddedildi.
John Ashmore

6
Bu iğrenç, @Samsung.
dokkaebi

3
Çıktıktan sonra ne yapmak istediğinize bağlıdır. Durum korunursa ve yalnızca geri gidebiliyorsanız, bir iletişim kutusu gösterilmesi gerekli olmayabilir. Ancak, uygulamalarımdan birinde çerezleri, verileri temizler ve bağlantıları son veriyle iyice temizlerim. Kullanıcı, özellikle mobil uygulamada bu sonluk hissine sahip olmak nadiren görüleceği için, seçimlerinin kesinliği konusunda bilgilendirilmelidir.
Eric

15
@ Tom R: Kesinlikle katılmıyorum. Kazayla bitirmek istemediğiniz uygulamalar var. İş ortamında çalışıyorlar vb.
TomeeNS

Yanıtlar:


390

Android 2.0 ve sonraki sürümlerinde bu şöyle görünecektir:

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

Önceki sürümlerde şöyle görünecektir:

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

}

15
Ayrıca 2.0 ve üzeri sürümlerde, KeyDown developer.android.com/intl/zh-TW/reference/android/app/… üzerinden önerilen yeni bir onBackPressed olayı var Burada değişiklikler ve yeni önerilen yaklaşım hakkında konuşan bir bölüm var. developer.android.com/intl/zh-TW/sdk/android-2.0.html
Patrick Kafka

3
Burada arka anahtarı yakalamak için blog yazısı: android-developers.blogspot.com/2009/12/… Bunun, kullanıcının uygulamanızı bırakabileceği diğer yolları yakalamanıza izin vermediğini unutmayın: eve basma, bildirim seçme, telefon alma call, etc.
hackbod

Bu mükemmel çalışıyor ancak kullanıcıya gösterildiğinde kod yürütmeyi nasıl durduracaksınız?
anon58192932

buldum, bu harika bir çözüm: stackoverflow.com/questions/4381296/…
anon58192932

1
Bu aradığım yöntem () ama bu yöntemi () çağırmak için nerede bilmiyordum.
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();
}

5
ElBradford tarafından bir yorum yapıldı: superBackPressed'i çağırmak, onBackPressed'i çağırmanın yalnızca finish () işlevini çağıracağını varsaymaktan daha iyidir. Şimdi bu doğru olsa bile, gelecekteki API'lerde doğru olmayabilirCustomTabActivity.super.onBackPressed
mplungjan

@mplungjan Yorumunuzu netleştirebilir misiniz ? finish()Kodu değiştirmenin daha iyi olduğunu mu söylüyorsunuz super.onBackPressed()?
ban-geoengineering

Yorum 3 yaşında. 2015'te iyi uygulama nedir bilmiyorum
mplungjan

@mplungjan Yorumunuz gelecekteki API'lara atıfta bulundu, ancak yine de açıklığa kavuşturmak yararlı olabilir.
ban-geoengineering

Sorun yok. Sadece denedim MyActivity.super.onBackPressed();ve benim için iyi çalışıyor. Çoğu mantıklı yaklaşım da öyle görünüyor - kullanıcı "Hayır" a dokunduğunda standart davranışı istiyorsanız geçersiz kıldığınız yöntemi çağırmak.
ban-geoengineering

33

@ User919216 kodunu değiştirmiş ve WebView ile uyumlu hale getirmiş

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

}

22

Bir çıkış İletişim Kutusundan daha arka düğmeye çift dokunarak çıkmayı tercih ederim.

Bu çözümde, ilk kez geri döndüğünüzde bir tost gösterir, başka bir geri basmanın Uygulamayı kapatacağını bildirir. Bu örnekte 4 saniyeden az.

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

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


Dialogbox hantal olabileceğinden bu kesinlikle benim favorim. 3 saniye yapmak için biraz değiştirdim ve bu işaretleyici ile biraz daha doğal görünüyor. Gönderi için teşekkürler.
PGMacDesign

çift ​​geri basın ideal app çıkmak gerekir ama benim kodda bir oturum açma açık Etkinlik (etkin spinner ile geri aktivite anlamına gelir)
techDigi

21

"Geri" çağrısının uygulamadan çıkıp çıkmayacağından veya kullanıcıyı başka bir etkinliğe götürüp götürmeyeceğinden emin değilseniz, yukarıdaki yanıtları bir isTaskRoot () işaretiyle sarabilirsiniz. Bu, ana etkinliğiniz arka yığına birden çok kez eklenebiliyorsa veya arka yığın geçmişinizi değiştiriyorsanız oluşabilir.

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

5

Lambda kullanma:

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

Ayrıca, gradle'ınızda java 8'i desteklemek için düzey dili ayarlamanız gerekir.

compileOptions {
       targetCompatibility 1.8
       sourceCompatibility 1.8
}

5

Çin'de, çoğu App "iki kez tıklayın" ile çıkış teyit edecektir:

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

5

İlk kaldır super.onBackPressed();dan onbackPressed()daha ve kod aşağıda yöntemle:

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

}

2

@GLee yaklaşımını beğendim ve aşağıdaki gibi parçalarla kullanmayı seviyorum.

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

Parçayı kullanan iletişim kutusu:

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

İlk aktivite, ben ortada faaliyet koyamazsınız. çünkü şimdi jsut mevcut etkinliği kapatıyor ve bir öncekini gösteriyor
shareef

1

Başka bir seçenek de , çıkıştan tekrar geri basmak isteyen ilk geri basımda bir Toast/ göstermekSnackbar , AlertDialogkullanıcının uygulamadan çıkmak isteyip istemediğini onaylamak için bir göstermekten çok daha az müdahaleci olmaktır.

Bunu DoubleBackPress Android Librarybirkaç kod satırı ile elde etmek için kullanabilirsiniz . Benzer davranışı gösteren GIF örneği.

Başlangıç ​​olarak, uygulamanıza bağımlılığı ekleyin:

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

Ardından, Etkinliğinizde gerekli davranışı uygulayın.

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

Son olarak, bunu geri basındaki davranış olarak ayarlayın.

@Override
public void onBackPressed() {
    doubleBackPress.onBackPressed();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.