Wie erhalte ich das aktuell angezeigte Fragment?

444

Ich spiele mit Fragmenten in Android.

Ich weiß, dass ich ein Fragment mithilfe des folgenden Codes ändern kann:

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

Meine Frage ist, wie ich in einer Java-Datei die aktuell angezeigte Fragment-Instanz erhalten kann.

Leem.fin
quelle
Verwandte - stackoverflow.com/a/21104084/80428
Jay Wick
1
Mögliches Duplikat von Get the current fragment object
Sruit A.Suk

Antworten:

453

Wenn Sie das Fragment zu Ihrer Transaktion hinzufügen, sollten Sie ein Tag verwenden.

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

... und später, wenn Sie überprüfen möchten, ob das Fragment sichtbar ist:

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

Siehe auch http://developer.android.com/reference/android/app/Fragment.html

Ramdroid
quelle
74
Ok, aber ich brauche eine Möglichkeit, um die aktuell angezeigte Fragmentinstanz sofort abzurufen, nicht iterativ alle Fragmente zu überprüfen und dann zu entscheiden, welches Fragment jetzt auf dem Bildschirm angezeigt wird. Ich denke, Ihre Antwort benötigt meinen Code, um jedes meiner Fragmente iterativ zu überprüfen und das sichtbare herauszufinden ...
Leem.fin
33
Ja, aber es kann mehr als ein Fragment gleichzeitig sichtbar sein. Es gibt also nichts
Besseres
6
Ok, auch wenn mehrere Fragmente angezeigt werden, brauche ich noch einen Weg, um sie zu erhalten ... und einen Weg, der besser ist, als jedes meiner Fragmente iterativ zu überprüfen. Ich bin besorgt darüber, eine Methode wie getDisplayedFragment () "zu bekommen", bin mir aber nicht sicher, ob es eine solche Methode in Android gibt
Leem.fin
2
Ich weiß nicht, warum dies ein Problem für Sie ist ... Sie haben normalerweise nur wenige Fragmente in einer Aktivität und es sollte eigentlich kein Problem sein, sie zu überprüfen, ob sie sichtbar sind oder nicht.
Ramdroid
12
Warum stimmen alle dieser Antwort zu? Sicher, es ist ein schönes Stück Code, aber es beantwortet nicht die Frage, ob ein bestimmtes Fragment per Tag abgerufen werden soll. ABER Asker möchte das aktuell angezeigte Fragment, was bedeutet, dass er nicht weiß, welches Fragment angezeigt wird. Ja, es kann mehrere Fragmente geben, aber das Lesen der Frage ergibt, dass nur 1 Fragment auf der Benutzeroberfläche angezeigt wird. Leider musste ich abstimmen, da es den Fragenkontext nicht beantwortet.
AngryITguy
410

Ich weiß, dass es ein alter Beitrag ist, hatte aber vorher auch Probleme damit. Eine Lösung gefunden, die dies in der onBackStackChanged()Hörfunktion tun sollte

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

    }

Dies funktionierte für mich, da ich nicht jedes Fragment durchlaufen wollte, um eines zu finden, das sichtbar ist. Hoffe, es hilft auch jemand anderem.

Sev
quelle
13
Genau das, wonach ich gesucht habe, als ich mich mit onBackPressed () nach Bildschirmdrehung mit einer Navigationsschublade befasst habe. Vielen Dank, dass Sie zurückgekommen sind, um dies zu teilen.
ShortFuse
1
Durchläuft findFragmentById nicht alle Fragmente intern? :)
Andrew Senner
46
Falls .getFragmentManagerinkompatibler Typ android.support.app.v4.FragmentgetSupportFragmentManager
Răzvan Barbu
3
oder Sie können findFragmentByTag()anstelle von verwenden findFragmentById, wenn Sie Tag zum Fragmentieren beim Hinzufügen zufragmentManager.beginTransaction() .add(containerID, frag, fragmentTag) .addToBackStack(fragmentTag) .commit();
DeltaCap019
@ AndrewSenner, er meint, er wollte es nicht explizit tun :)
Farid
159

Hier ist meine Lösung, die ich für Szenarien mit geringen Fragmenten nützlich finde

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
quelle
13
fragmentkann in bestimmten Szenarien null sein, z. B. wenn Sie den Backstack öffnen. Also besser nutzen if (fragment != null && fragment.isVisible()).
Cprcrack
8
Methode unvollständig, weil es möglich ist, dass nicht nur ein Fragment sichtbar ist
letroll
Wenn kein Fragment sichtbar ist, gibt fragmentManager.getFragments () NULL zurück, was dazu führt, dass NPE sagt: "Versuch, die Schnittstellenmethode 'java.util.Iterator java.util.List.iterator ()' für eine NULL-Objektreferenz aufzurufen". Daher sollte die for-Schleife von einer einfachen Prüfung umgeben sein: if (Fragmente! = Null)
Pranav Mahajan
Was ist, wenn mehr als ein Fragment sichtbar ist?
Shivaraj Patil
5
Technisch sollte dies als Antwort basierend auf der Frage markiert werden. Asker möchte ein aktuell angezeigtes Fragment, ohne zu wissen, um welches Fragment es sich handelt. Andere Antworten erhalten immer wieder Fragmente von Tag
AngryITguy
76

Jedes Mal, wenn Sie ein Fragment anzeigen, müssen Sie es in den Hintergrund stellen:

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

Und wenn Sie dann ein aktuelles Fragment benötigen, können Sie diese Methode verwenden:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
Dmitry_L
quelle
4
Ich bin mir ziemlich sicher, dass diese Technik für Fragmente, die mit einem ViewPager verwendet werden, nicht funktioniert, da sie nicht per Tag hinzugefügt werden. Wirf das einfach raus.
Loeschg
3
Dies scheint nur zu funktionieren, wenn Sie aufrufen addToBackStack(tag), aber was ist, wenn Sie das Fragment nicht zum Backstack hinzufügen möchten?
Cprcrack
1
Dies funktioniert nur, wenn Ihr Tag zufällig mit dem Namen des Backstacks übereinstimmt, was ungewöhnlich erscheint.
Was passiert, wenn Sie 5 Fragmente in derselben Transaktion hinzugefügt haben?
Kevin Lam
Es ist vielleicht schön zu sagen, dass, wenn Sie addToBackStack (null) für ein Fragment aufrufen, für das Sie keinen Namen benötigen, die Methode getName () null zurückgeben kann und Sie eine NPE erhalten. @ dpk, docu sagt: Ruft den Namen ab, der FragmentTransaction.addToBackStack (String) beim Erstellen dieses Eintrags übergeben wurde. Fügen Sie außerdem eine Nullprüfung hinzu, wenn EntryCount 0 ist und Sie versuchen, den obersten Eintrag zu erhalten.
JacksOnF1re
23

Was ich verwende, um das aktuelle Anzeigefragment zu finden, befindet sich im folgenden Code. Es ist einfach und funktioniert mittlerweile bei mir. Es läuft in der Aktivität, die die Fragmente enthält

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
tainy
quelle
3
Sie sollten überprüfen, ob count> 0 ist, damit get (count-1) keine IndexOutofBoundsException auslöst
kehers
@tainy dies wird nicht das Fragment geben, das ersetzt, aber nicht zum Backstack hinzugefügt wurde. Richtig? Wenn ja, kann ich es dann mit dem Tag-Argument erhalten?
Cafebabe1991
Der Aufruf von getFragments gibt den Fragmenten nicht die Reihenfolge, in der sie hinzugefügt wurden, nachdem Sie popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) aufgerufen haben, und fügt weitere Fragmente hinzu.
LEHO
Wenn bei Aktivitäten mehr als ein Fragment sichtbar ist, ist Ihr Weg falsch. Zum Beispiel: ViewPager mit Fragmenten. Wie ich wusste, gibt getBackStackEntryCount () die Nummer der Transaktion zurück, nicht die Nummer des Fragments
HungNM2
Sie sollten überprüfen, fragManager.getFragments().size()anstatt, getBackStackEntryCount()da sie nicht unbedingt gleich sind (was mein Fall ist). Andernfalls können Sie mit IndexOutOfBoundsException
RustamG
19

Kotlin Weg;

val currentFragment = supportFragmentManager.fragments.last()
Cafer Mert Ceyhan
quelle
Funktioniert nur mit API 26 und
höher
1
@ibit was meinst du mit funktioniert nur mit API 26 und höher? Ich habe versucht, Emulator API 19 funktioniert einwandfrei.
HendraWD
@HendraWD du bist richtig! Ich bezog mich auf die Funktion in der Framework- getFragments()Funktion, die API 26 und höher ist.
ibit
2
sich kümmern. Wenn Sie zuvor keinen Fragmentstapel haben, kann dies zu einer leeren Ausnahme führen!
Jetwiz
Das funktioniert nicht? java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment kann nicht in Fragment
coolcool1994
13

Der reaktive Weg:

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });
localhost
quelle
7
Wie ist das reaktiv? Sie verwenden ein Observable, aber es wird nur einmal ausgestrahlt
Tim
6
Und es ist nur ein Overkill. Ein einfacher erweiterter Forloop würde genau das Gleiche tun, vielleicht sogar noch schneller.
Peterstev Uremgba
Die Verwendung eines reaktiven Streams nur für die Stream-API ist nicht so klug. Wie gesagt, es ist ein Overkill. Verwenden Sie die Steam-Java8-API, wenn Sie die Liste als Stream behandeln und die Filter-API anwenden
möchten
13

Meine Methode basiert auf try / catch wie folgt:

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

Aber es kann einen besseren Weg geben ...

Thordax
quelle
1
Meine Frage ist, wie man das aktuell angezeigte Fragment erhält, was bedeutet, dass es viele Fragmente geben kann. Ich möchte nur die Instanz des aktuell angezeigten erhalten, warum sollte ich (MyFragment) verwenden? Ich meine, es könnte jede Fragmentanzeige auf dem Bildschirm sein ... und ich möchte die aktuell angezeigte erhalten.
Leem.fin
MY_TAG_FRAGMENT ist das Tag des Fragments, das ich vor der Verwendung eines Ersetzers erstellt habe: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT);
Thordax
Wenn ich mehrere Fragmente habe, kann ich beim Aufruf von .replace (...) ein Tag für alle Fragmente verwenden?
Leem.fin
Ja, kein Problem, verwenden Sie diesen Code: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); und es kann gut gehen.
Thordax
1
Nun, ich verstehe Ihren Standpunkt wirklich nicht, ich meine, ich brauche eine Möglichkeit, um die aktuell angezeigte Fragmentinstanz sofort zu erhalten, nicht iterativ alle Fragmente zu überprüfen und dann zu entscheiden, welches Fragment jetzt auf dem Bildschirm angezeigt wird.
Leem.fin
11

Nun, diese Frage erhielt viele Ansichten und Aufmerksamkeit, enthielt aber immer noch nicht die einfachste Lösung von meinem Ende - getFragments () zu verwenden.

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);
Nativ
quelle
1
Leider ist dies nicht immer der Fall. getSupportFragmentManager().getFragments() Sie erhalten eine Liste zurück, die jedoch Nullwerte enthalten kann, wenn das neueste Fragment gerade aus dem Backstack entfernt wurde. Gl.: Wenn Sie sich innerhalb der onBackStackChanged()Methode vergewissern und popBackStack()irgendwo anrufen , mCurrentFragmentwird das sein null.
Stumi
@ Stumi Danke für diese Information. Ja, klingt nach einem von vielen seltsamen Lebenszyklusproblemen in Android.
Nativ
9

Sie können abfragen, welches Fragment in Ihren Aktivitäten-Inhaltsrahmen geladen wird, und die Fragmentklasse oder das Fragment 'einfacher Name' (als Zeichenfolge) abrufen.

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

Verwendungszweck:

Log.d(TAG, getCurrentFragment());

Ausgänge:

D/MainActivity: FragOne
Herr L.
quelle
8

Es ist etwas spät, aber für alle, die interessiert sind: Wenn Sie den Index Ihres gewünschten Fragments in FragmentManager kennen, holen Sie sich einfach einen Verweis darauf und suchen Sie nach der Funktion isMenuVisible ()! Hier :

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

Wenn es truefür den Benutzer sichtbar ist und so weiter!

MohammadReza
quelle
1
Seltsamerweise war dies die einzige hier aufgeführte Lösung, die für mich funktioniert hat. Gleichzeitig können mehrere Fragmente haben isVisible() == true, getView() != null. Außerdem ist in meinem Code getBackStackEntryCountimmer Null. Obwohl ich keine Menüs verwende, isMenuVisible()ist dies bislang die einzige Diskriminante, die zuverlässig auf das derzeit "aktive" Fragment zu verweisen scheint. 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
quelle
6

Wenn Sie hierher kommen und Kotlin verwenden:

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

R.id.fragment_containerist das, idwo das fragmentauf ihrem präsentiertactivity

Oder wenn Sie eine schönere Lösung wollen:

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

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}
Pableiros
quelle
5

Inspiriert von Tainys Antwort, hier sind meine zwei Cent. Wenig modifiziert von den meisten anderen Implementierungen.

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

Ersetzen Sie "myActivity"durch "dies", wenn es sich um Ihre aktuelle Aktivität handelt oder verwenden Sie einen Verweis auf Ihre Aktivität.

Nashe
quelle
5

Es gibt eine Methode namens findFragmentById()in SupportFragmentManager. Ich benutze es im Aktivitätscontainer wie:

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

So erhalten Sie Ihren Strom Fragment. Wenn Sie benutzerdefinierte haben Fragmentund überprüfen müssen, was Fragmentes ist, verwende ich normalerweise instanceof:

if (currentFragment() instanceof MyFrag){
    // Do something here
}
Kevin Murvie
quelle
5

Wenn Sie Folgendes verwenden AndroidX Navigation:

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

Weitere Informationen zu dieser Navigationskomponente finden Sie unter: https://developer.android.com/guide/navigation/navigation-getting-started

Cory Roy
quelle
Dies wird nicht kompiliert
IgorGanapolsky
1
Es würde nur kompiliert, wenn Sie die AndroidX-Navigation richtig eingerichtet und Ihren navHost irgendwie aufgerufen hätten your_navhost.
Cory Roy
4

Dies ist ein einfacher Weg, um das aktuelle Fragment zu erhalten.

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
quelle
4

Sevs Antwort funktioniert, wenn Sie die Zurück-Taste drücken oder auf andere Weise den Backstack ändern.

Ich habe allerdings etwas anderes gemacht. Ich habe ein Backstack-Change-Listener-Setup für ein Basisfragment und seine abgeleiteten Fragmente, und dieser Code befindet sich im Listener:

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
quelle
3

Das ist Arbeit für mich. Ich hoffe, das wird jemandem helfen.

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

Wenn Sie die aktuelle Instanz von Fragment aus der übergeordneten Aktivität erhalten, können Sie dies einfach tun

findFragmentByID(R.id.container);

Dies ist tatsächlich die aktuelle Instanz des Fragments, die in der Ansicht ausgefüllt ist. Ich hatte das gleiche Problem. Ich musste dasselbe Fragment zweimal laden und eines auf dem Backstack halten.

Die folgende Methode funktioniert nicht. Es wird nur ein Fragment mit dem Tag angezeigt. Verschwenden Sie keine Zeit mit dieser Methode. Ich bin sicher, dass es seine Verwendung hat, aber die neueste Version desselben Fragments zu erhalten, gehört nicht dazu.

findFragmentByTag()
Yasin Yaqoobi
quelle
3

Testen Sie diese Lösung. Es hat bei mir funktioniert, das aktuelle Fragment zu bekommen.

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
quelle
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");
}
KeranMarinov
quelle
Das funktioniert mit Jetpack?
IgorGanapolsky
2
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

Nun, ich denke, dies ist die direkteste Antwort auf diese Frage. Ich hoffe das hilft.

Abhishek
quelle
2

Hier ist eine Kotlin-Lösung:

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

Vereinfachter Weg:

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

Einfacher Weg, das zu tun:

Fragment fr=getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String fragmentName = fr.getClass().getSimpleName();
Biplob Das
quelle
1

In der Hauptaktivität wird die Methode onAttachFragment (Fragmentfragment) aufgerufen, wenn ein neues Fragment an die Aktivität angehängt wird. Bei dieser Methode können Sie die Instanz des aktuellen Fragments abrufen. Die onAttachFragment-Methode wird jedoch nicht aufgerufen, wenn ein Fragment vom Backstack entfernt wird, dh wenn die Zurück-Taste gedrückt wird, um das oberste Fragment auf den Stapel zu legen. Ich suche immer noch nach einer Rückrufmethode, die in der Hauptaktivität ausgelöst wird, wenn ein Fragment innerhalb der Aktivität sichtbar wird.

Entwickler
quelle
so nah! :-)
Blundell
Wir benutzen die Jetpack Navigation Bibliothek
IgorGanapolsky
1

Bei gescrollten Fragmenten können Sie, wenn Sie eine Instanz der ViewPager-Klasse verwenden, mVeiwPager, mViewPager.getCurrentItem () aufrufen, um die aktuelle Fragment-Int-Nummer abzurufen.

in 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>

in 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
quelle
1

Ich fand findFragmentByTages nicht so bequem. Wenn Sie String currentFragmentTagin Ihrem Activityoder Elternteil haben Fragment, müssen Sie es speichern onSaveInstanceStateund wiederherstellen onCreate. Selbst wenn Sie dies tun, wenn die Activityneu erstellt, onAttachFragmentwird vor genannt onCreate, so dass Sie nicht verwenden können , currentFragmentTagin onAttachFragment(z. B. einige Ansichten aktualisieren basierend aufcurrentFragmentTag ), weil es die Macht noch nicht wiederhergestellt.

Ich benutze den folgenden Code:

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

Das Dokument des FragmentManagerStaates, dass

Die Reihenfolge der Fragmente in der Liste ist die Reihenfolge, in der sie hinzugefügt oder angehängt wurden.

Wenn Sie Dinge tun müssen, die auf dem aktuellen Fragmenttyp basieren, verwenden Sie einfach getCurrentFragment() instance of MyFragmentanstelle von currentFragmentTag.equals("my_fragment_tag").

Beachten Sie, dass getCurrentFragment()in onAttachFragmentnicht das Anhängen Fragment, sondern das vorherige angehängte erhalten wird.

Jeffrey Chen
quelle
1

Ich musste dies erst kürzlich tun und keine der Antworten hier passte wirklich zu diesem Szenario.

Wenn Sie sicher sind, dass nur ein Fragment sichtbar ist (Vollbild), möchten Sie wirklich herausfinden, was sich oben im Backstack befindet. Zum Beispiel, als ein Kotlinfür 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)
        }
    }
}

Und benutze es wie:

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

        setVisibilityChangeListener(this::class.java) { visible -> 
            // Do stuff
        }
    }
}
Mikel Pascual
quelle
1

Sie können dies sehr einfach auch mit einer URL in logcat tun, die Sie zum Quellcode des aktuellen Fragmentquellcodes umleitet. Zunächst müssen Sie einen OnBackStackChangedListener in Host-Aktivitäten wie - hinzufügen.

activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);

Und die OnBackStackChangedListener- Implementierung ist -

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

Und die Methode getStackTopName () lautet -

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
quelle