Programlı olarak backstack'taki önceki parçaya geri dön


218

Diyelim ki programlı olarak eklenen parçalara sahip bir etkinliğim var:

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

Görünür olan önceki parçaya geri dönmenin en iyi yolu nedir?

Android'de düğme tıklamasında Tetik geri düğmesi işlevini buldum , ancak geri anahtar bir etkinliği simüle etmenin doğru yol olmadığını düşünüyorum (ve ben de işe yarayamıyorum):

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

Aramak finish(), ilgilenmediğim etkinliği kapatır.

Bununla ilgili daha iyi bir yol var mı?

Yanıtlar:


354

Bak getFragmentManager().popBackStack()yöntemlerle (seçim için çeşitli vardır)

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


91
getFragmentManager().popBackStackImmediate();hile yaptı. Teşekkürler.
Aske B.

1
Bu yöntemi nereye koyardım? Sekme dinleyicimde mi?
rasen58

1
kodu görmeden söylemek zor ... ama geçerli parçayı "kapatmak" ve önceki parçaya geri dönmek istediğinizde yürütülen kod bölümüne gitmelisiniz.
stuckless

1
getSupportFragmentManager ()
ViliusK

5
Kodunuza "addToBackStack (" tag ")" eklemeyi unutmayın. "(etiket"). fragmentManager.beginTransaction () (R.id.content_frame, fragmanı) .addToBackStack yerine "() işlemek;." addToBackStack (null) yazarsanız, bunu tek başına halleder, ancak bir etiket verirseniz, bunu manuel olarak ele almanız gerekir.
Khaled Saif

129

Sağlanan diğer cevapları detaylandırmak için, bu benim çözümümdür (bir Faaliyete yerleştirilir):

@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
ve bu neden oluyor. Parça örneği developer.android.com/training/basics/fragments/index.html'de , geri basınçlandırılmış olayı geçersiz kılmıyorlar ve yine de parçayı geri takip edebiliyorlar. Ben trasaction.addToBackStack (null) kullandım; ama hiçbir şey olmadı. Nedenini açıklayabilir misin ?
Murtaza Khursheed Hussain

@MurtazaHussain Bu konuda yardım istiyorsanız muhtemelen yeni bir soru sormalısınız. Daha fazla koda bakmadan neler olduğunu görmek biraz zor.
Kyle Falconer

2
Benim durumumda fm.getBackStackEntryCount() > 1, sadece yığının ilk parçası olduğunda etkinliği geri çağırmak için yapmam gerekiyordu .
Facundo Olano

3
Android bunu sizin için zaten yapıyor: "Arka yığında FragmentTransaction nesneleri olduğunda ve kullanıcı Geri düğmesine bastığında, FragmentManager en son işlemi arka yığından çıkarır ve ters işlemi gerçekleştirir (işlemin bir parçayı kaldırma gibi) ekledi). " (Kaynak)
artkoenig

29

Parçaları güncellerken / eklerken,

İçermeli .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();

Bundan sonra getFragments.popBackStackImmediate(), parçaları eklersek / güncellersek ve geçerli ekrana geri dönersek , will true döndürür.


7

Bu satırı onBackPressed () Yönteminize ekleyin. Geri yığınında herhangi bir parça varsa popBackStackImmediate () yöntemi sizi önceki parçaya geri götürür.

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

'


5

Bu çözüm, birincil parçaya tekrar basıldığında uygulamayı kapatmak istediğinizde alt çubuk tabanlı parça navigasyonu için mükemmel çalışır.

Diğer yandan kodumda "AyrıntılıPizza" olarak tanımlanan ikincil fragmanı (fragmandaki fragman) açarken, birincil fragmanın önceki durumuna dönecektir. Şerefe!

Sırttaki preslenmiş iç aktiviteler şunları söyledi:

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

Ve diğer parçayı şöyle başlatın:

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

3

Eğer parça hareketime eklenen addToBackStack () yoksa bu cevaplar işe yaramaz, ancak kullanabilirsiniz:

getActivity().onBackPressed();

bir adım geri gitmek için herhangi bir parçanızdan;


1

Aşağıdaki kodu kullanarak programlı olarak önceki parçaya geri dönün.

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

1

Bu parçanın tekrar gelmesini sağlamak için, bu parçayı basılı olarak geri dönmek istediğiniz backstack'e ekleyin, ör:

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

Yukarıdaki durumda, basıldığında açıyorum LoginFragment, Button buttonşu anda kullanıcı içeride SignupFragment. Yani addToBackStack(TAG)denirse, nerede TAG = "SignupFragment", o zaman geri düğmesine basıldığında LoginFragment, geri döneriz SignUpFragment.

Mutlu Kodlama!


TAG'ın etkilemediğini düşünüyorum, hatta belki de null.
CoolMind

1

fragment_tran.addToBackStack(null)Son parçaya ekleyerek , son parçaya geri dönebilirim.

yeni parça ekleme :

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

Buraya bakarken ya da aynı fikri geldim ve bu arada kendime geldim, ki bu o kadar da kötü değil ve ViewPager ile çalışıyorsa.

Yaptığım şey, viewPager'i tutan üst etkinlikte onBackPressed yöntemini geçersiz kılmak ve her zaman ilk parçaya ulaşana kadar eksi 1 konumuna geri dönüp etkinliği kapatacak şekilde ayarlamaktır.

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

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

Bunun bir çöküşü olabilir, her seferinde yalnızca bir yol geri gider, bu yüzden sekmeler varsa ve atlanmış parçalarla konumları değiştirirseniz (0'dan 2'ye gitmek ve daha sonra geri basmak sizi işe yaratırsa harika çalışmayabilir). 1 yerine 0)

Benim durumum tho, viewPager sekmeler olmadan 2 parçaları ile, bu işi güzel yapar.


Benzer soru zaten cevaplandı. stackoverflow.com/questions/10863572/…
AtifSayings

0

Aşağıdaki kodu deneyin:

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