karena pertanyaan ini dan beberapa jawabannya sudah lebih dari lima tahun, izinkan saya berbagi solusi. Ini adalah tindak lanjut dan modernisasi jawaban dari @oyenigun
UPDATE:
Di bagian bawah artikel ini, saya menambahkan implementasi alternatif menggunakan ekstensi Fragmen abstrak yang tidak akan melibatkan Kegiatan sama sekali, yang akan berguna bagi siapa pun dengan hierarki fragmen yang lebih kompleks yang melibatkan fragmen bersarang yang membutuhkan perilaku punggung yang berbeda.
Saya perlu menerapkan ini karena beberapa fragmen yang saya gunakan memiliki tampilan lebih kecil yang ingin saya abaikan dengan tombol kembali, seperti tampilan informasi kecil yang muncul, dll, tetapi ini bagus untuk siapa saja yang perlu menimpa perilaku tombol kembali di dalam fragmen.
Pertama, tentukan Antarmuka
public interface Backable {
boolean onBackPressed();
}
Antarmuka ini, yang saya sebut Backable
(saya stickler untuk konvensi penamaan), memiliki metode tunggal onBackPressed()
yang harus mengembalikan boolean
nilai. Kita perlu menegakkan nilai boolean karena kita perlu tahu apakah tekan tombol kembali telah "menyerap" acara kembali. Kembali true
berarti sudah, dan tidak ada tindakan lebih lanjut diperlukan, jika tidak, false
mengatakan bahwa tindakan kembali standar masih harus dilakukan. Antarmuka ini harus berupa file sendiri (lebih disukai dalam paket terpisah bernama interfaces
). Ingat, memisahkan kelas Anda ke dalam paket adalah praktik yang baik.
Kedua, temukan fragmen atas
Saya membuat metode yang mengembalikan Fragment
objek terakhir di tumpukan belakang. Saya menggunakan tag ... jika Anda menggunakan ID, buat perubahan yang diperlukan. Saya memiliki metode statis ini di kelas utilitas yang berhubungan dengan status navigasi, dll ... tapi tentu saja, letakkan di tempat yang paling cocok untuk Anda. Untuk perbaikan, saya telah memasukkan milik saya di kelas yang disebut NavUtils
.
public static Fragment getCurrentFragment(Activity activity) {
FragmentManager fragmentManager = activity.getFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
String lastFragmentName = fragmentManager.getBackStackEntryAt(
fragmentManager.getBackStackEntryCount() - 1).getName();
return fragmentManager.findFragmentByTag(lastFragmentName);
}
return null;
}
Pastikan jumlah tumpukan kembali lebih besar dari 0, jika tidak, ArrayOutOfBoundsException
dapat dilempar saat runtime. Jika tidak lebih besar dari 0, kembalikan nol. Kami akan memeriksa nilai nol nanti ...
Ketiga, Implementasikan dalam Fragmen
Menerapkan Backable
antarmuka di bagian mana pun di mana Anda perlu mengganti perilaku tombol kembali. Tambahkan metode implementasi.
public class SomeFragment extends Fragment implements
FragmentManager.OnBackStackChangedListener, Backable {
...
@Override
public boolean onBackPressed() {
// Logic here...
if (backButtonShouldNotGoBack) {
whateverMethodYouNeed();
return true;
}
return false;
}
}
Dalam onBackPressed()
mengganti, masukkan logika apa pun yang Anda butuhkan. Jika Anda ingin tombol kembali tidak memunculkan tumpukan belakang (perilaku default), kembali benar , bahwa acara kembali Anda telah diserap. Jika tidak, kembalikan salah.
Terakhir, di Aktivitas Anda ...
Ganti onBackPressed()
metode dan tambahkan logika ini ke dalamnya:
@Override
public void onBackPressed() {
// Get the current fragment using the method from the second step above...
Fragment currentFragment = NavUtils.getCurrentFragment(this);
// Determine whether or not this fragment implements Backable
// Do a null check just to be safe
if (currentFragment != null && currentFragment instanceof Backable) {
if (((Backable) currentFragment).onBackPressed()) {
// If the onBackPressed override in your fragment
// did absorb the back event (returned true), return
return;
} else {
// Otherwise, call the super method for the default behavior
super.onBackPressed();
}
}
// Any other logic needed...
// call super method to be sure the back button does its thing...
super.onBackPressed();
}
Kami mendapatkan fragmen saat ini di tumpukan belakang, kemudian kami melakukan pemeriksaan nol dan menentukan apakah itu mengimplementasikan Backable
antarmuka kami . Jika ya, tentukan apakah acara itu diserap. Jika demikian, kita sudah selesai onBackPressed()
dan dapat kembali. Kalau tidak, perlakukan itu sebagai tekan kembali normal dan panggil metode super.
Opsi kedua untuk tidak melibatkan Aktivitas
Kadang-kadang, Anda sama sekali tidak ingin Kegiatan menangani ini, dan Anda perlu menanganinya secara langsung di dalam fragmen. Tetapi siapa yang bilang Anda tidak bisa memiliki Fragmen dengan back press API? Cukup rentangkan fragmen Anda ke kelas baru.
Buat kelas abstrak yang memperluas Fragmen dan mengimplementasikan View.OnKeyListner
antarmuka ...
import android.app.Fragment;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public abstract class BackableFragment extends Fragment implements View.OnKeyListener {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(this);
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackButtonPressed();
return true;
}
}
return false;
}
public abstract void onBackButtonPressed();
}
Seperti yang Anda lihat, setiap fragmen yang meluas BackableFragment
akan secara otomatis menangkap kembali klik menggunakan View.OnKeyListener
antarmuka. Panggil saja onBackButtonPressed()
metode abstrak dari dalam onKey()
metode yang diimplementasikan menggunakan logika standar untuk membedakan tekan tombol kembali. Jika Anda perlu mendaftarkan klik kunci selain tombol kembali, pastikan untuk memanggil super
metode ketika menimpa onKey()
fragmen Anda, jika tidak Anda akan menimpa perilaku di abstraksi.
Mudah digunakan, cukup rentangkan dan terapkan:
public class FragmentChannels extends BackableFragment {
...
@Override
public void onBackButtonPressed() {
if (doTheThingRequiringBackButtonOverride) {
// do the thing
} else {
getActivity().onBackPressed();
}
}
...
}
Karena onBackButtonPressed()
metode di kelas super abstrak, setelah Anda memperluas Anda harus menerapkan onBackButtonPressed()
. Ini kembali void
karena hanya perlu melakukan tindakan dalam kelas fragmen, dan tidak perlu menyampaikan penyerapan pers kembali ke Aktivitas. Pastikan Anda memanggil onBackPressed()
metode Aktivitas jika apa pun yang Anda lakukan dengan tombol kembali tidak memerlukan penanganan, jika tidak, tombol kembali akan dinonaktifkan ... dan Anda tidak menginginkan itu!
Peringatan
Seperti yang Anda lihat, ini mengatur pendengar kunci ke tampilan root dari fragmen, dan kita harus memfokuskannya. Jika ada teks edit yang terlibat (atau tampilan mencuri fokus lainnya) dalam fragmen Anda yang memperluas kelas ini, (atau fragmen dalam lainnya atau tampilan yang memiliki yang sama), Anda harus mengatasinya secara terpisah. Ada artikel bagus tentang cara memperpanjang EditText untuk kehilangan fokus pada tekanan balik.
Saya harap seseorang menemukan ini berguna. Selamat coding.