Jak uzyskać aktualnie wyświetlany fragment?

444

Gram z fragmentami w Androidzie.

Wiem, że mogę zmienić fragment, używając następującego kodu:

FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();

MyFragment myFragment = new MyFragment(); //my custom fragment

fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();

Moje pytanie brzmi: w pliku Java, jak mogę uzyskać aktualnie wyświetlaną instancję Fragment?

Leem.fin
źródło
Powiązane - stackoverflow.com/a/21104084/80428
Jay Wick
1
Możliwy duplikat Pobierz bieżący obiekt fragmentu
Sruit A.Suk

Odpowiedzi:

453

Po dodaniu fragmentu do transakcji należy użyć znacznika.

fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");

... a później, jeśli chcesz sprawdzić, czy fragment jest widoczny:

MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
   // add your code here
}

Zobacz także http://developer.android.com/reference/android/app/Fragment.html

ramdroid
źródło
74
Ok, ale potrzebuję sposobu, aby natychmiast uzyskać aktualnie wyświetlaną instancję Fragmentu, nie sprawdzać iteracyjnie wszystkich fragmentów, a następnie zdecydować, który fragment jest teraz wyświetlany na ekranie. Myślę, że twoja odpowiedź wymaga mojego kodu, aby iteracyjnie sprawdzić każdy z moich fragmentów i znaleźć ten widoczny ...
Leem.fin
33
Tak, ale jednocześnie może być widoczny więcej niż jeden fragment. Nie ma więc nic takiego jak „jedyny aktywny fragment” ....
ramdroid
6
Ok, nawet wyświetlono kilka fragmentów, wciąż potrzebuję sposobu, aby je zdobyć ... i sposobu, który jest lepszy niż iteracyjne sprawdzenie każdego z moich fragmentów. Jestem troska o „je” metoda jak getDisplayedFragment (), ale nie wiem, czy istnieje taka metoda w Androidzie
Leem.fin
2
Nie wiem, dlaczego jest to dla ciebie problem ... Zazwyczaj masz tylko kilka fragmentów w działaniu i sprawdzenie, czy są widoczne, nie powinno być problemem.
ramdroid
12
Dlaczego wszyscy popierają tę odpowiedź? Jasne, to niezły fragment kodu, ale nie odpowiada na pytanie, aby uzyskać konkretny fragment po tagu. ALE Asker chce aktualnie wyświetlanego fragmentu, co oznacza, że ​​nie wie, który fragment jest wyświetlany. Tak, może istnieć wiele fragmentów, ale po przeczytaniu pytania w interfejsie użytkownika wyświetla się tylko 1 fragment ... Przepraszam, że muszę głosować, ponieważ nie odpowiada on na kontekst pytania.
angryITguy
410

Wiem, że to stary post, ale wcześniej miałem z tym problem. Znaleziono rozwiązanie, które miało to zrobić w onBackStackChanged()funkcji odsłuchu

  @Override
    public void onBackPressed() {
        super.onBackPressed();

         Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
      if(f instanceof CustomFragmentClass) 
        // do something with f
        ((CustomFragmentClass) f).doSomething();

    }

To działało dla mnie, ponieważ nie chciałem powtarzać każdego fragmentu, który muszę znaleźć, który jest widoczny. Mam nadzieję, że pomoże to również komuś innemu.

Sev
źródło
13
Dokładnie to, czego szukałem podczas pracy z funkcją onBackPressed () po obróceniu ekranu za pomocą szuflady nawigacji. Dziękujemy za przyjście i podzielenie się tym.
ShortFuse
1
Czy findFragmentById nie wykonuje iteracji przez wszystkie fragmenty wewnętrznie? :)
Andrew Senner
46
w przypadku .getFragmentManagerraportów typu niezgodnego, tak jak w moim przypadku, dzieje się tak, ponieważ korzystałem z android.support.app.v4.Fragment, w którym to przypadku właściwą metodą jestgetSupportFragmentManager
Răzvan Barbu
3
lub możesz użyć findFragmentByTag()zamiast findFragmentById, jeśli podałeś tag do fragmentowania podczas dodawania go dofragmentManager.beginTransaction() .add(containerID, frag, fragmentTag) .addToBackStack(fragmentTag) .commit();
DeltaCap019
@AndrewSenner, ma na myśli, że nie chciał tego robić wprost :)
Farid
161

Oto moje rozwiązanie, które uważam za przydatne w scenariuszach z niskim fragmentem

public Fragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    if(fragments != null){
        for(Fragment fragment : fragments){
            if(fragment != null && fragment.isVisible())
                return fragment;
        }
    }
    return null;
}
Matt Mombrea
źródło
13
fragmentmoże mieć wartość null w niektórych scenariuszach, na przykład podczas otwierania tylnego stosu. Więc lepiej użyj if (fragment != null && fragment.isVisible()).
cprcrack
8
metoda niekompletna, ponieważ jest możliwe, że nie widać tylko jednego fragmentu
wypisz
Jeśli żaden fragment nie jest widoczny, fragmentManager.getFragments () zwróci NULL, co spowoduje, że NPE powie „Próba wywołania metody interfejsu java.util.Iterator java.util.List.iterator ()” w odniesieniu do obiektu NULL ”. Dlatego pętla for powinna być otoczona prostym sprawdzeniem: if (fragmenty! = Null)
Pranav Mahajan
Co jeśli więcej niż jeden fragment jest widoczny?
Shivaraj Patil
5
Technicznie należy to oznaczyć jako odpowiedź na podstawie pytania. Pytający chce aktualnie wyświetlanego fragmentu, nie wiedząc, który to fragment. Inne odpowiedzi wciąż zdobywają fragmenty według tagu
złyITguy
76

Za każdym razem, gdy pokazujesz fragment, musisz umieścić go w plecaku:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);       
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();        

A kiedy potrzebujesz uzyskać aktualny fragment, możesz użyć tej metody:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
Dmitry_L
źródło
4
Jestem całkiem pewien, że ta technika nie zadziała w przypadku fragmentów używanych z ViewPager, ponieważ nie są one dodawane przez znacznik. Po prostu to tam rzucam.
loeschg
3
Wydaje się, że działa to tylko wtedy, gdy zadzwonisz addToBackStack(tag), ale co zrobić, jeśli nie chcesz dodać fragmentu do tylnego stosu?
cprcrack
1
Działa to tylko wtedy, gdy twój tag jest taki sam jak nazwa stosu tylnego, co wydaje się niezwykłe.
Co się stanie, jeśli dodasz 5 fragmentów w tej samej transakcji?
Kevin Lam
Być może miło jest powiedzieć, że jeśli wywołasz addToBackStack (null) dla jakiegoś Fragmentu, w którym nie potrzebujesz nazwy, metoda getName () może zwrócić null i otrzymasz NPE. @ dpk, docu mówi: Uzyskaj nazwę, która została dostarczona do FragmentTransaction.addToBackStack (String) podczas tworzenia tego wpisu. Dodaj także zerowe sprawdzenie, czy EntryCount ma wartość 0, i próbujesz otrzymać najwyższy wpis.
JacksOnF1re
23

To, czego używam do znalezienia bieżącego fragmentu wyświetlania, znajduje się poniżej kodu. To jest proste i do tej pory działa dla mnie. Działa w aktywności, która zawiera fragmenty

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
tainy
źródło
3
Powinieneś sprawdzić, aby upewnić się, że liczba> 0, aby get (count-1) nie generował wyjątku IndexOutofBoundsException
kehers
@tainy to nie da fragmentu, który został zastąpiony, ale nie został dodany do backstacka. Prawda? Jeśli tak, to czy mogę to uzyskać za pomocą argumentu tag?
cafebabe1991
Wywołanie getFragments nie da ci fragmentów w kolejności, w jakiej zostały dodane po wywołaniu popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) na nim i dodania kolejnych fragmentów.
LEHO
jeśli aktywność ma więcej niż jeden Fragment widoczny, Twoja droga jest zła. Na przykład: ViewPager z fragmentami. jak wiadomo getBackStackEntryCount () zwraca numer Transakcji, a nie liczbę fragmentów
HungNM2
Powinieneś sprawdzić fragManager.getFragments().size()zamiast, getBackStackEntryCount()ponieważ niekoniecznie są one równe (w moim przypadku). W przeciwnym razie możesz dostać awarię z IndexOutOfBoundsException
RustamG
19

Sposób Kotlina;

val currentFragment = supportFragmentManager.fragments.last()
Kawiarnia Mert Ceyhan
źródło
Działa tylko z API 26 i
nowszymi
1
@ibit, co masz na myśli mówiąc, że działa tylko na API 26 i nowszych wersjach? Próbowałem na emulatorze API 19 działającym dobrze.
HendraWD,
@HendraWD masz rację! Miałem na myśli funkcję w ramach frameworka getFragments(), którą jest API 26 i nowsze.
ibit
2
dbać. Jeśli wcześniej nie masz stosu fragmentów, może to spowodować pusty wyjątek!
Jetwiz,
To nie działa? java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment nie mogą być oddane do Fragment
coolcool1994
13

Reaktywne sposób:

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });
Lokalny Gospodarz
źródło
7
jak to jest reaktywne? Używasz obserwowalnego, ale wyemituje się tylko raz
Tim
6
I to tylko przesada. Prosty ulepszony forloop zrobiłby to samo, może nawet szybciej.
Peterstev Uremgba
używanie reaktywnego strumienia do samego streamu API nie jest tak inteligentne, w rzeczywistości, jak powiedzieli, że to przesada, użyj Steam Java API, jeśli chcesz traktować listę jako strumień i zastosować interfejs API
AndroidLover
13

Moja metoda oparta jest na try / catch:

MyFragment viewer = null;
    if(getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT) instanceOf MyFragment){
    viewer = (MyFragment) getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT);
}

Ale może być lepszy sposób ...

Thordax
źródło
1
Moje pytanie brzmi: jak uzyskać aktualnie wyświetlany fragment, co oznacza, że ​​może być wiele fragmentów, chcę tylko uzyskać instancję aktualnie wyświetlanego fragmentu, dlaczego warto używać (MyFragment)? Mam na myśli, że może to być dowolny fragment Fragmentu na ekranie ... i chcę, aby ten był aktualnie wyświetlany.
Leem.fin
MY_TAG_FRAGMENT jest znacznikiem fragmentu, który utworzyłem przed użyciem zastępowania, takiego jak: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT);
Thordax,
Jeśli mam wiele fragmentów, czy mogę użyć jednego znacznika dla wszystkich fragmentów podczas wywołania .replace (...)?
Leem.fin
Tak, nie ma problemu, użyj tego kodu: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); i może pójść dobrze.
Thordax,
1
Cóż, naprawdę nie rozumiem, o co mi chodzi, to znaczy, że potrzebuję sposobu, aby natychmiast uzyskać aktualnie wyświetlaną instancję Fragmentu, nie iteracyjnie sprawdzać wszystkie fragmenty, a następnie zdecydować, który fragment jest teraz wyświetlany na ekranie.
Leem.fin
11

Cóż, to pytanie zyskało wiele poglądów i uwagi, ale wciąż nie zawierało najłatwiejszego rozwiązania z mojej strony - użycia getFragments ().

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);
Nativ
źródło
1
Niestety, nie zawsze jest to prawdą, getSupportFragmentManager().getFragments() daje ci listę, ale może zawierać wartości zerowe, jeśli najnowszy fragment został właśnie wyskakujący z backstacka. Eq: Jeśli sprawdzisz swoją drogę wewnątrz onBackStackChanged()metody i wywołasz popBackStack()gdzieś, to mCurrentFragmentbędzie null.
Stumi,
@Stumi Dzięki za tę informację. Tak, brzmi jak jeden z wielu dziwnych problemów cyklu życia w Androidzie.
Nativ
9

Możesz zapytać, który fragment jest załadowany do ramki treści Działania, i pobrać klasę fragmentu lub fragment „prostej nazwy” (jako ciąg).

public String getCurrentFragment(){
     return activity.getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
}

Stosowanie:

Log.d(TAG, getCurrentFragment());

Wyjścia:

D/MainActivity: FragOne
Pan L.
źródło
8

Jest trochę późno, ale dla każdego, kto jest zainteresowany: jeśli znasz indeks żądanego fragmentu w FragmentManager, po prostu uzyskaj odwołanie do niego i sprawdź, czy jest funkcja isMenuVisible ()! tutaj:

getSupportFragmentManager().getFragments().get(0).isMenuVisible()

Jeśli jest truewidoczny dla użytkownika i tak dalej!

MohammadReza
źródło
1
O dziwo, było to jedyne wymienione tutaj rozwiązanie, które działało dla mnie. Jednocześnie, wiele fragmentów może mieć isVisible() == true, getView() != null. Dodatkowo w moim kodzie getBackStackEntryCountjest zawsze zero. Mimo że nie korzystam z menu, isMenuVisible()to jak dotąd jedyna dyskryminacja, która wydaje się niezawodnie wskazywać na aktualnie „aktywny” fragment. ty
parvus
7

1)

ft.replace(R.id.content_frame, fragment, **tag**).commit();

2)

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);

3)

if (currentFragment.getTag().equals(**"Fragment_Main"**))
{
 //Do something
}
else
if (currentFragment.getTag().equals(**"Fragment_DM"**))
{
//Do something
}
Nam Ngo Thanh
źródło
6

Jeśli się tu dostaniesz i korzystasz z Kotlin:

var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)

R.id.fragment_containerto miejsce, w idktórym fragmentprezentuje się na nichactivity

Lub jeśli chcesz ładniejszego rozwiązania:

supportFragmentManager.findFragmentById(R.id.content_main)?.let {
    // the fragment exists

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}
pableiros
źródło
5

Zainspirowany odpowiedzią Tainy , oto moje dwa centy. Trochę zmodyfikowany w stosunku do większości innych implementacji.

private Fragment getCurrentFragment() {
    FragmentManager fragmentManager = myActivity.getSupportFragmentManager();
    int stackCount = fragmentManager.getBackStackEntryCount();
    if( fragmentManager.getFragments() != null ) return fragmentManager.getFragments().get( stackCount > 0 ? stackCount-1 : stackCount );
    else return null;
}

Zamień na "myActivity"„to”, jeśli jest to Twoja bieżąca aktywność, lub użyj odniesienia do swojej aktywności.

Nashe
źródło
5

Jest to metoda nazywa findFragmentById()się SupportFragmentManager. Używam go w kontenerze aktywności, takim jak:

public Fragment currentFragment(){
    return getSupportFragmentManager().findFragmentById(R.id.activity_newsfeed_frame);
}

Tak zdobędziesz swój prąd Fragment. Jeśli masz niestandardowy Fragmenti chcesz sprawdzić, co Fragmentto jest, zwykle używam instanceof:

if (currentFragment() instanceof MyFrag){
    // Do something here
}
Kevin Murvie
źródło
5

Jeśli używasz AndroidX Navigation:

val currentFragment = findNavController(R.id.your_navhost).?currentDestination

Aby uzyskać więcej informacji na temat tego elementu nawigacyjnego: https://developer.android.com/guide/navigation/navigation-getting-started

Cory Roy
źródło
To się nie kompiluje
IgorGanapolsky
1
Kompilowałby się tylko, jeśli poprawnie skonfigurowałeś nawigację na AndroidX i jakoś nazwałeś navHost your_navhost.
Cory Roy
4

Jest to prosty sposób na uzyskanie bieżącego fragmentu.

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override public void onBackStackChanged() {
    currentFragment = fragmentManager.findFragmentById(R.id.content);
    if (currentFragment !=  null && (currentFragment instanceof LoginScreenFragment)) {
      logout.setVisibility(View.GONE);
    } else {
      logout.setVisibility(View.VISIBLE);
    }
  }
});
lallu Sukendh
źródło
4

Odpowiedź Seva działa, gdy naciśniesz przycisk Wstecz lub w inny sposób zmienisz plecak.

Zrobiłem jednak coś nieco innego. Mam konfigurację detektora zmian cofnięcia na podstawowym fragmencie i jego pochodnych fragmentach, a ten kod znajduje się w detektorze:

Fragment f = getActivity().getSupportFragmentManager().findFragmentById(R.id.container);

if (f.getClass().equals(getClass())) {
    // On back button, or popBackStack(),
    // the fragment that's becoming visible executes here,
    // but not the one being popped, or others on the back stack

    // So, for my case, I can change action bar bg color per fragment
}
MCLLC
źródło
3

To dla mnie praca. Mam nadzieję, że to komuś pomoże.

FragmentManager fragmentManager = this.getSupportFragmentManager();  
        String tag = fragmentManager
                    .getBackStackEntryAt(
                    fragmentManager
                    .getBackStackEntryCount() - 1)
                    .getName();
              Log.d("This is your Top Fragment name: ", ""+tag);
Cüneyt
źródło
3

Jeśli pobierasz bieżącą instancję Fragmentu z działania nadrzędnego, możesz to zrobić

findFragmentByID(R.id.container);

To faktycznie jest bieżącą instancją fragmentu, który jest zapełniany w widoku. Miałem ten sam problem. Musiałem załadować ten sam fragment dwa razy, trzymając jeden z powrotem na stos.

Następująca metoda nie działa. Po prostu dostaje fragment, który ma tag. Nie trać czasu na tę metodę. Jestem pewien, że ma on swoje zastosowania, ale uzyskanie najnowszej wersji tego samego fragmentu nie jest jednym z nich.

findFragmentByTag()
Yasin Yaqoobi
źródło
3

Sprawdź to rozwiązanie. Udało mi się zdobyć obecny Fragment.

if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        android.support.v4.app.Fragment f = 
         getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if(f instanceof ProfileFragment){
            Log.d(TAG, "Profile Fragment");
        }else if(f instanceof SavedLocationsFragment){
            Log.d(TAG, "SavedLocations Fragment");
        }else if(f instanceof AddLocationFragment){
            Log.d(TAG, "Add Locations Fragment");
        }
Haroon Khan
źródło
2
final FragmentManager fm=this.getSupportFragmentManager();
final Fragment fragment=fm.findFragmentByTag("MY_FRAGMENT");

if(fragment != null && fragment.isVisible()){
      Log.i("TAG","my fragment is visible");
}
else{
      Log.i("TAG","my fragment is not visible");
}
kmarin
źródło
To działa z Jetpack?
IgorGanapolsky
2
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

Sądzę, że jest to najprostsza odpowiedź na to pytanie. Mam nadzieję, że to pomoże.

Abhishek
źródło
2

Oto rozwiązanie Kotlin:

if ( this.getSupportFragmentManager().getBackStackEntryCount()>0 ) {
    var fgmt = this.getSupportFragmentManager().fragments[this.getSupportFragmentManager().getBackStackEntryCount()-1]
    if( fgmt is FgmtClassName ) {
        (fgmt as FgmtClassName).doSth()
    }
}

Uproszczony sposób:

with ( this.getSupportFragmentManager() ) {
    if ( getBackStackEntryCount()>0 ) {
        var fgmt = fragments[getBackStackEntryCount()-1]
        if ( fgmt is FgmtClassName ) {
            (fgmt as FgmtClassName).doSth()
        }
    }
}
anamkin
źródło
2

Łatwy sposób to zrobić:

Fragment fr=getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String fragmentName = fr.getClass().getSimpleName();
Biplob Das
źródło
1

W głównym działaniu metoda onAttachFragment (fragment fragmentu) jest wywoływana, gdy do działania dołączany jest nowy fragment. W tej metodzie można uzyskać instancję bieżącego fragmentu. Jednak metoda onAttachFragment nie jest wywoływana, gdy fragment jest usuwany ze stosu, tj. Gdy naciśnięty jest przycisk Wstecz, aby uzyskać górny fragment na szczycie stosu. Nadal szukam metody wywołania zwrotnego, która jest uruchamiana w głównej aktywności, gdy fragment staje się widoczny w tej aktywności.

ufdeveloper
źródło
tak blisko! :-)
Blundell
Używamy biblioteki nawigacji Jetpack
IgorGanapolsky
1

W przypadku przewijanych fragmentów, gdy używasz instancji klasy ViewPager, załóżmy, że mVeiwPager, możesz wywołać mViewPager.getCurrentItem () w celu uzyskania bieżącego numeru int.

w MainLayout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context="unidesign.photo360.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="false"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:expanded="false">

        <android.support.v7.widget.Toolbar
            android:id="@+id/main_activity_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:title="@string/app_name">

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>


    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </android.support.v4.view.ViewPager>
    
</android.support.design.widget.CoordinatorLayout>

w MainActivity.kt

class MainActivity : AppCompatActivity() {
    
        lateinit var mViewPager: ViewPager
        lateinit var pageAdapter: PageAdapter
        
//      ...
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            
            pageAdapter = PageAdapter(supportFragmentManager)
            mViewPager = findViewById(R.id.view_pager)
//          ...
            }
            
        override fun onResume() {
          super.onResume()
          var currentFragment = pageAdapter.getItem(mViewPager.currentItem)
//         ...
          }

Andrei Radchenko
źródło
1

Odkryłem, że findFragmentByTagto nie jest wygodne. Jeśli masz String currentFragmentTagu swojego Activitylub rodzica Fragment, musisz go zapisać onSaveInstanceStatei przywrócić onCreate. Nawet jeśli to zrobisz, po Activityodtworzeniu onAttachFragmentzostanie wywołany wcześniej onCreate, więc nie możesz użyć currentFragmentTagw onAttachFragment(np. Zaktualizować niektórych widoków na podstawiecurrentFragmentTag ), ponieważ może nie zostać jeszcze przywrócone.

Używam następującego kodu:

Fragment getCurrentFragment() {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if(fragments.isEmpty()) {
        return null;
    }
    return fragments.get(fragments.size()-1);
}

Dokument FragmentManagerstwierdzający, że

Kolejność fragmentów na liście to kolejność, w której zostały dodane lub dołączone.

Jeśli musisz robić rzeczy na podstawie bieżącego typu fragmentu, po prostu użyj getCurrentFragment() instance of MyFragmentzamiast currentFragmentTag.equals("my_fragment_tag").

Zauważ, że getCurrentFragment()w onAttachFragmentnie otrzyma załączania Fragment, ale poprzedni załączony.

Jeffrey Chen
źródło
1

Musiałem to zrobić bardzo niedawno i żadna z odpowiedzi tutaj nie pasowała do tego scenariusza.

Jeśli masz pewność, że widoczny będzie tylko jeden fragment (pełny ekran), więc naprawdę chcesz znaleźć to, co znajduje się na górze plecaka. Na przykład, jak Kotlinna Fragment:

import androidx.fragment.app.Fragment

fun Fragment.setVisibilityChangeListener(clazz: Class<out Fragment>, listener: (Boolean) -> Unit) {
    fragmentManager?.run {
        addOnBackStackChangedListener {
            val topFragmentTag = getBackStackEntryAt(backStackEntryCount - 1).name
            val topFragment = findFragmentByTag(topFragmentTag)
            listener(topFragment != null && topFragment::class.java == clazz)
        }
    }
}

I używaj go w następujący sposób:

class MyFragment: Fragment {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setVisibilityChangeListener(this::class.java) { visible -> 
            // Do stuff
        }
    }
}
Mikel Pascual
źródło
1

Możesz to zrobić bardzo łatwo również za pomocą adresu URL w logcat, który przekieruje cię do kodu źródłowego bieżącego kodu źródłowego fragmentu. Najpierw musisz dodać OnBackStackChangedListener do działania hosta, takiego jak -

activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);

A implementacja OnBackStackChangedListener to -

    public FragmentManager.OnBackStackChangedListener backStackListener = () -> {

    String simpleName = "";
    String stackName = getStackTopName().trim();

    if (Validator.isValid(stackName) && stackName.length() > 0) {

      simpleName = stackName.substring(Objects.requireNonNull(stackName).lastIndexOf('.') + 1).trim();

      List<Fragment >
       fragmentList = getChildFragmentManager().getFragments();
      Fragment myCurrentFragment;

      for (int i = 0; i < fragmentList.size(); i++) {
       myCurrentFragment= fragmentList.get(i);
       if (myCurrentFragment.getClass().getSimpleName().equals(simpleName)) {
        //Now you get the current displaying fragment assigned in myCurrentFragment.
        break;
       }
       myFragment = null;
      }
     }


     //The code below is for the source code redirectable logcat which would be optional for you.
     StackTraceElement stackTraceElement = new StackTraceElement(simpleName, "", simpleName + ".java", 50);
     String fileName = stackTraceElement.getFileName();
     if (fileName == null) fileName = "";
     final String info = "Current Fragment is:" + "(" + fileName + ":" +
     stackTraceElement.getLineNumber() + ")";
     Log.d("now", info + "\n\n");
    };

A metoda getStackTopName () to -

public String getStackTopName() {
    FragmentManager.BackStackEntry backEntry = null;
    FragmentManager fragmentManager = getChildFragmentManager();
    if (fragmentManager != null) {
        if (getChildFragmentManager().getBackStackEntryCount() > 0)
            backEntry = getChildFragmentManager().getBackStackEntryAt(
                    getChildFragmentManager().getBackStackEntryCount() - 1
            );
    }
    return backEntry != null ? backEntry.getName() : null;
}
Gk Mohammad Emon
źródło