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?

Jawaban:


354

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

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


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

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.


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

`


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

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;


1

Secara terprogram kembali ke fragmen sebelumnya menggunakan kode berikut.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();

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!


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

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.


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();
            }
        }
    }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.