Secara terprogram kembali ke fragmen sebelumnya di backstack

218

Katakanlah saya memiliki aktivitas yang memiliki fragmen yang ditambahkan secara terprogram:

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

Apa cara terbaik untuk kembali ke fragmen sebelumnya yang terlihat?

Saya menemukan fungsi tombol kembali Pemicu pada klik tombol di Android tapi saya berpikir mensimulasikan peristiwa tombol kembali bukan cara yang tepat untuk melakukannya (dan saya juga tidak bisa membuatnya berfungsi):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

Menelepon finish()hanya menutup aktivitas yang saya tidak tertarik.

Apakah ada cara yang lebih baik untuk melakukan ini?

Aske B.
sumber

Jawaban:

354

Lihatlah getFragmentManager().popBackStack()metodenya (ada beberapa yang bisa dipilih)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack ()

macet
sumber
91
getFragmentManager().popBackStackImmediate();melakukan trik. Terima kasih.
Aske B.
1
Di mana saya akan meletakkan metode ini? Di pendengar tab saya?
rasen58
1
tanpa melihat kodenya, sulit untuk mengatakan ... tetapi itu harus pergi di bagian kode yang dieksekusi ketika Anda ingin "menutup" fragmen saat ini dan kembali ke fragmen sebelumnya.
macet
1
bagaimana dengan getSupportFragmentManager ()
ViliusK
5
Jangan lupa untuk menambahkan "addToBackStack (" tag ")" dalam kode Anda. "fragmentManager.beginTransaction (). ganti (R.id.content_frame, fragment) .addToBackStack (" tag "). commit ();" jika Anda menulis addToBackStack (null), ia akan menanganinya sendiri tetapi jika Anda memberi tag, Anda harus mengatasinya secara manual.
Khaled Saif
129

Untuk menguraikan jawaban lain yang disediakan, ini adalah solusi saya (ditempatkan di Aktivitas):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}
Kyle Falconer
sumber
5
dan mengapa itu terjadi. Dalam contoh fragmen developer.android.com/training/basics/fragments/index.html mereka tidak mengabaikan acara yang di-tekan-ulang namun mereka mampu meng-backstack fragmen. Saya telah menggunakan trasaction.addToBackStack (null); tetapi tidak ada yang terjadi. Bisakah Anda jelaskan mengapa?
Murtaza Khursheed Hussain
@MurtazaHussain Anda mungkin harus mengajukan pertanyaan baru jika Anda ingin bantuan dengan ini. Agak sulit untuk melihat apa yang terjadi tanpa melihat lebih banyak kode.
Kyle Falconer
2
Dalam kasus saya, saya harus melakukan fm.getBackStackEntryCount() > 1untuk memanggil aktivitas kembali ketika hanya ada fragmen pertama di tumpukan.
Facundo Olano
3
Android sudah melakukan ini untuk Anda: "Ketika ada objek FragmentTransaction di tumpukan belakang dan pengguna menekan tombol Kembali, FragmentManager mengeluarkan transaksi terbaru dari tumpukan belakang dan melakukan tindakan sebaliknya (seperti menghapus fragmen jika transaksi menambahkannya). " (Sumber)
artkoenig
29

Ketika kami memperbarui / menambahkan fragmen,

Harus Termasuk .addToBackStack().

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

Setelah itu jika kita memberi getFragments.popBackStackImmediate()akan mengembalikan true jika kita menambah / memperbarui fragmen, dan kembali ke layar saat ini.

Jabeer
sumber
7

Tambahkan baris tersebut ke Metode onBackPressed () Anda. Metode popBackStackImmediate () akan membawa Anda kembali ke fragmen sebelumnya jika Anda memiliki fragmen di back stack `

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

`

Avijit Biswas
sumber
5

Solusi ini berfungsi sempurna untuk navigasi fragmen berbasis bar bawah ketika Anda ingin menutup aplikasi ketika ditekan kembali dalam fragmen primer.

Di sisi lain ketika Anda membuka fragmen sekunder (fragmen dalam fragmen) yang didefinisikan sebagai "DetailedPizza" dalam kode saya, itu akan mengembalikan keadaan sebelumnya dari fragmen primer. Bersulang !

Aktivitas di dalam ditekan kembali menempatkan ini:

Fragment home = getSupportFragmentManager().findFragmentByTag("DetailedPizza");

if (home instanceof FragmentDetailedPizza && home.isVisible()) {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
} else {
    //Primary fragment
    moveTaskToBack(true);
}

Dan luncurkan fragmen lain seperti ini:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();
Giedrius Šlikas
sumber
3

Jawaban ini tidak berfungsi jika saya tidak menambahkan addToBackStack () ke transaksi fragmen saya tetapi, Anda dapat menggunakan:

getActivity().onBackPressed();

dari setiap fragmen Anda untuk mundur satu langkah;

Biplob Das
sumber
1

Secara terprogram kembali ke fragmen sebelumnya menggunakan kode berikut.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();
Piyush MandaliYa
sumber
1

Untuk membuat fragmen itu kembali, cukup tambahkan fragmen itu ke backstack yang ingin Anda tekan kembali, misalnya:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

Dalam kasus di atas, saya membuka LoginFragmentsaat Button buttonditekan, saat ini pengguna sedang masuk SignupFragment. Jadi jika addToBackStack(TAG)dipanggil, di mana TAG = "SignupFragment", lalu ketika tombol kembali ditekan LoginFragment, kita kembali ke SignUpFragment.

Selamat Coding!

Saurabh Singh
sumber
Saya pikir, TAG tidak mempengaruhi, bahkan mungkin nol.
CoolMind
1

Dengan menambahkan fragment_tran.addToBackStack(null)fragmen terakhir, saya bisa kembali pada fragmen terakhir.

menambahkan fragmen baru :

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });
Baljinder Maan
sumber
1

Saya datang ke sini mencari atau ide yang sama, dan sementara itu saya datang dengan sendiri, yang saya percaya tidak terlalu buruk dan berfungsi jika dengan ViewPager.

Jadi yang saya lakukan adalah mengganti metode onBackPressed dalam aktivitas induk yang memegang viewPager, dan mengaturnya untuk selalu kembali ke posisi minus 1 hingga mencapai fragmen pertama, kemudian menutup aktivitas.

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

Ini mungkin memiliki kejatuhan, seperti itu hanya kembali satu arah ke kiri setiap kali, jadi mungkin tidak berfungsi dengan baik jika ada tab dan Anda beralih posisi dengan potongan-potongan yang dilompati, (pergi dari 0 ke 2, dan kemudian menekan kembali akan menempatkan Anda pada 1, bukannya 0)

Untuk kasus saya, dengan 2 fragmen di viewPager tanpa tab, ini berfungsi dengan baik.

Grzesiek Eman
sumber
Pertanyaan serupa sudah dijawab. stackoverflow.com/questions/10863572/…
AtifSayings
0

Coba kode di bawah ini:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }
Adarsh
sumber