Kendini kaldırmak için bir Parça nasıl elde edilir, yani finish () eşdeğeri?


230

Uyumluluk kütüphanesini kullanarak parçaları kullanmak için bir uygulamayı dönüştürüyorum. Şu anda birbirine zincirleme bir dizi faaliyetim (ABCD) var, D'ye basıldığında aramalar bittiğinde onActivityResult()C ve B'yi yok etmek için havaya uçuyor.

Ön Honycomb fragman versiyonum için her aktivite etkili bir şekilde Af Bf Cf Df fragmanları üzerine bir sargıdır. Tüm aktiviteler aracılığıyla başlatılır startActivityForResult()ve onActivityResult()her bir parça içinde mutlu bir şekilde arayabilirgetActivity().finish()

Gerçi benim sorunum benim Petek sürümünde sadece bir aktivite var, A ve parçaları Bf, Cf, Df kullanılarak yüklenir FragmentManager.

Anlamadığım Df, Cf ve Bf parçalarını kaldırmak için 'OK' tuşuna basıldığında Df'de ne yapmalı?

Parçanın kendisini yığınının dışına atmayı denedim ama bu bir istisna ile sonuçlandı. onActivityResult()yararsızdır çünkü parçayı kullanarak yüklemedim startActivityForResult().

Bunu tamamen yanlış bir şekilde düşünüyor muyum? İşlem yöneticisini kullanarak pop'u yapmak için üst parça veya etkinlikle iletişim kuran bir tür dinleyici mi uygulamalıyım?


7
ne hakkında ((YourActivity) getActivity ()). onBackPressed ();
Viswanath Lekshmanan

@ViswanathLekshmanan Yorumun yanıtı benim için yararlı .. 1 Benden oy al
Abhishek Singh

@AbhishekSingh Duymak güzel :)
Viswanath Lekshmanan

@ViswanathLekshmanan :)
Abhishek Singh

Yanıtlar:


62

Anlamadığım Df, Cf ve Bf parçalarını kaldırmak için 'OK' tuşuna basıldığında Df'de ne yapmalı?

Adım # 1: Df D "yo! Biz OK tıklayın var!" etkinliğin kendisinde veya etkinlik tarafından sağlanan arabirim örneğinde bir yöntem çağrılarak.

Adım # 2: D ile parçaları çıkarın FragmentManager.

Barındırma faaliyeti (D), aktivitede başka fragmanların ne olduğunu bilen aktivitedir (diğer aktivitelerde olmak yerine). Bu nedenle, fragman karışımını etkileyebilecek fragman içi olaylar, uygun düzenleme hareketlerini yapacak olan aktiviteye yayılmalıdır.


Ama benim Petek versiyonumda D yok, bu benim zor. Sadece FragmentTransaction kullanarak Df yükleyen Cf yükleyen Bf parçasını yükleyen bir A aktivitesi vardır.
PJL

1
@PJL: Üzgünüm, A. demek istedim. Bu bir dinleyici arayüzü kullanmak için bir neden, bu yüzden birden fazla faaliyetin hepsi Df'den "OK click got" etkinliğine yanıt verebilir.
CommonsWare

1
Şu anda taşıdığım gibi ben daha sonra FragmentManager üzerinde popBackStack çağırdı etkinliği içine Df onActivityResult yöntemi parçalarından bir dinleyici yöntemi çağırdı. Ancak, bu bir istisna ile sonuçlanır "IllegalStateException: onSaveInstanceState 'sonra bu eylem gerçekleştirilemez. Bunun üstesinden gelmek için herhangi bir fikir?
PJL

1
@DiegoPalomar: finish()yeterli olmalı.
CommonsWare

1
@ user3364963: Bunu araştırmamdan bu yana bir süre geçti, ancak IIRC, arka yığından attığında yok edildi. Parçanıza bir onDestroy()yöntem ekleyin ve çağrılıp çağrılmadığına bakın.
CommonsWare

313

En iyi yaklaşım olmasa da, işe yaradığını düşünebileceğim en yakın eşdeğer destek / uyumluluk kütüphanesi ile budur

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

veya

getActivity().getFragmentManager().beginTransaction().remove(this).commit();

aksi takdirde.

Ayrıca backstack'ı kullanabilir ve pop yapabilirsiniz. Bununla birlikte, parçanın backstack üzerinde olmayabileceğini unutmayın (oraya ulaşan fragmenttransaction'a bağlı olarak) veya yığına giren son kişi olmayabilir, bu nedenle yığını patlatmak yanlış olanı kaldırabilir ...


11
Bu yaklaşım çalışırken, addToBackStack (null) kullanıyorsanız geri düğmesi işleyicisini +1 bırakacaktır. Yani iki kez basmanız gerekecek.
user123321

34
Parçayı FragmentManager'dan "pop" yapın.
user123321

2
Yukarıdaki yordamı denedim ama bu hatayı "java-lang-illegalstateexception-can-gerçekleştiremez-bu-eylem-on-affinstance" veriyor. Tam olarak nerede parçayı kaldırmak zorunda
KK_07k11A0585 15:13

6
Bu cevap kötü bir uygulamadır ve oy kullanmamak gerekir. Fragmanlar bu şekilde kendini tanıyacak şekilde tasarlanmamıştır. Parçaların noktası olan yeniden kullanılabilirliği öldürür! Parça, herhangi bir sayıda yoldan uzaklaştırılması için aktiviteyi işaret etmelidir. Geri arama arabirimi yöntemi popüler bir seçimdir. developer.android.com/training/basics/fragments/…
colintheshots

2
@ManfredMoser katılmıyorum. Sorunun konusu budur. Kaldırmak için bir dizi parçaya sahip. Bu kodda, etkinliğin iliştirilip eklenmediğini kontrol veya boş kontrol yoktur. Üretimde kırılacak, çünkü bir parçanın bilmediği çok fazla şeye bağlı.
colintheshots

263

Aşağıdaki yaklaşımı kullanabilirsiniz, iyi çalışıyor:

getActivity().getSupportFragmentManager().popBackStack();

44
Bu cevap, kabul edilenden 10 kat daha iyi - doğrudan noktaya.
nikib3ro

50
Tasarım açısından da kabul edilene göre 10 kat daha kötü. Bir parçanın bir faaliyet için küçük bir "yardımcı" olması gerekiyordu ve asla kendisi veya diğer parçalar üzerinde kontrol edilmemelidir
Patrick

6
@Avalancha'nın işaret ettiği gibi çözüm doğru değil. Developer.android.com/guide/components/…
the_dark_destructor

2
Bu yöntemi onActivityResult kullanıyorum ve "onSaveInstanceState sonra bu eylem gerçekleştirilemiyor" hatası alıyorum. Nasıl çözebilirim?
Jayeshkumar Sojitra

1
popBackStack()parçayı sildikten sonra eylem çubuğu başlığını önceki duruma geri döndürmek istediğinizde çalışan tek çözümdür. Aksi takdirde , çeşitli kullanım durumlarından sonra her zaman uygun eylem çubuğu başlığını ayarlamak için stackoverflow.com/questions/13472258/… ' dan her iki yüksek dereceli çözümü ve bu çözümü burada birleştirmem gerekmeyecekti . geri basma, silme, değiştirme ekleme vb.
Bevor

36

CommonsWare'in dediği gibi, bir dinleyici kullanarak Parçaların eklenmesi ve çıkarılmasıyla ilgilenmesine izin vermelisiniz. İşte bir örnek:

public class MyActivity extends FragmentActivity implements SuicidalFragmentListener {

    // onCreate etc

    @Override
    public void onFragmentSuicide(String tag) {
        // Check tag if you do this with more than one fragmen, then:
        getSupportFragmentManager().popBackStack();
    }
}

public interface SuicidalFragmentListener {
    void onFragmentSuicide(String tag);
}

public class MyFragment extends Fragment {

    // onCreateView etc

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
           suicideListener = (SuicidalFragmentListener) activity;
        } catch (ClassCastException e) {
           throw new RuntimeException(getActivity().getClass().getSimpleName() + " must implement the suicide listener to use this fragment", e);
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Attach the close listener to whatever action on the fragment you want
        addSuicideTouchListener();
    }

    private void addSuicideTouchListener() {
        getView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              suicideListener.onFragmentSuicide(getTag());
            }
        });
    }
}

5
İntihar çok emo tarzı? "SelfClosing" veya "AutoClose" veya "SmartClose" (r)
DritanX

21
kapanmıyor DYING FOREVER ;-(
Blundell

3
Bu, diğer cevaplardan çok daha temiz bir yaklaşımdır. Etkinlik parçayı oluşturur ve sunar ve yaşam döngüsünü kontrol etmelidir. Parçanın artık görünmemesi gerektiğini gösteren bir şey olduğunda, Faaliyete bunu söylemeli ve etkinliğin onu kaldırmasına izin vermelidir.
Christopher Pickslay

7
Teknik olarak, eğer aktivitenin parçayı öldürmesi gerekiyorsa, o zaman parça intihar değildir. Aktivite cinayettir.
Casey Murray

17

Activity / AppCompatActivity'de:

@Override
public void onBackPressed() {
    if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
        // if you want to handle DrawerLayout
        mDrawerLayout.closeDrawer(GravityCompat.START);
    } else {
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            super.onBackPressed();
        } else {
            getFragmentManager().popBackStack();
        }
    }
}

ve sonra parçayı çağırınız:

getActivity().onBackPressed();

veya diğer cevaplarda belirtildiği gibi, bunu fragman olarak adlandırın:

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

5

Yeni Gezinme Bileşenini kullanıyorsanız,

findNavController().popBackStack()

Tüm FragmentTransaction'ı sizin için arkada yapacak.


4

İhtiyaçlarınızın bir DialogFragment tarafından karşılanıp karşılanmadığını görün. DialogFragment bir dismiss () yöntemine sahiptir. Bence çok daha temiz.


3

Bunun için basit bir yöntem oluşturuyorum

popBackStack(getSupportFragmentManager());

Daha sonra benim ActivityUtils sınıfına yerleştirin

public static void popBackStack(FragmentManager manager){
        FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
        manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

Harika çalışıyor, iyi eğlenceler!


2
Metodunuzun amacını anlamıyorum. Orijinal popBackStack tamamen yeterli görünüyor.
İnanılmaz Ocak

1

OnCreate:

//Add comment fragment
            container = FindViewById<FrameLayout>(Resource.Id.frmAttachPicture);
            mPictureFragment = new fmtAttachPicture();

            var trans = SupportFragmentManager.BeginTransaction();
            trans.Add(container.Id, mPictureFragment, "fmtPicture");
            trans.Show(mPictureFragment); trans.Commit();

Ben nasıl tıklama olayı parçası gizlemek budur 1

//Close fragment
    var trans = SupportFragmentManager.BeginTransaction();
    trans.Hide(mPictureFragment);
    trans.AddToBackStack(null);
    trans.Commit();

Sonra geri olay 2 gösterir

var trans = SupportFragmentManager.BeginTransaction();
            trans.Show(mPictureFragment); trans.Commit();

1

Backstack geçmişindeki dördüncü parçadan ilk parçaya geri dönmeniz gerekiyorsa, etiketleri kullanın !!!

İlk parçayı eklediğinizde şöyle bir şey kullanmalısınız:

getFragmentManager.beginTransaction.addToBackStack("A").add(R.id.container, FragmentA).commit() 

veya

getFragmentManager.beginTransaction.addToBackStack("A").replace(R.id.container, FragmentA).commit()

Ve B, C ve D Fragmanlarını göstermek istediğinizde bunu kullanırsınız:

getFragmentManager.beginTransaction.addToBackStack("B").replace(R.id.container, FragmentB, "B").commit()

ve diğer harfler ....

FragmentA'ya geri dönmek için popBackStack(0, "A"), evet'i çağırmanız yeterlidir, eklerken belirttiğiniz bayrağı kullanın ve bunun, addToBackStack()komut değiştirme veya ekleme işleminde kullanılanla değil, komutta aynı bayrak olması gerektiğini unutmayın .

Rica ederim ;)


Ben 'popBackStack (0, "A")' test ettik ve benim app A parçasına geri geliyor, ama ben sadece bu parça Geri Yığını kaldırılmasını istiyorum ... Nasıl ekranda göstermeden Yığını parça kaldırmak ??
KryNaC

1

Aynı parçanın içindeyken bir parçayı kapatmak için

getActivity().onBackPressed();

-9

Neden sadece:

getActivity () kaplama (.);


4
Bu sadece parçayı değil tüm aktiviteyi bitirecektir.
Murtadha S.
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.