How do I get the currently displayed fragment?

527,915

Solution 1

When you add the fragment in your transaction you should use a tag.

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

...and later if you want to check if the fragment is visible:

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

See also http://developer.android.com/reference/android/app/Fragment.html

Solution 2

I know it's an old post, but was having trouble with it previously too. Found a solution which was to do this in the onBackStackChanged() listening function

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

    }

This worked for me as I didn't want to iterate through every fragment I have to find one that is visible.

Solution 3

Here is my solution which I find handy for low fragment scenarios

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

Solution 4

Every time when you show fragment you must put it tag into backstack:

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

And then when you need to get current fragment you may use this method:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}

Solution 5

Kotlin way;

val currentFragment = supportFragmentManager.fragments.last()
Share:
527,915
Leem.fin
Author by

Leem.fin

A newbie in software development.

Updated on July 08, 2022

Comments

  • Leem.fin
    Leem.fin almost 2 years

    I am playing with fragments in Android.

    I know I can change a fragment by using the following code:

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

    My question is, in a Java file, how can I get the currently displayed Fragment instance?

  • Leem.fin
    Leem.fin over 12 years
    My question is how to get currently displayed fragment, which means there could be a lot of fragments, I only want to get the instance of the currently displayed one, why use (MyFragment) ?? I mean it could be any Fragment display on the screen...and I want to get the currently displayed one.
  • Thordax
    Thordax over 12 years
    MY_TAG_FRAGMENT is the tag of the fragment I created before using a replace, like this : fragmentTransaction.replace(R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT);
  • Leem.fin
    Leem.fin over 12 years
    If I have multiple fragments, can I use one tag for all the fragments when call .replace(...) ?
  • Thordax
    Thordax over 12 years
    Yes, no problem, use this code : fragmentTransaction.replace(R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); and it may go well.
  • Leem.fin
    Leem.fin over 12 years
    Ok, so if I use one tag for all fragments, once I findFragmentByTag(tag), it will returns me the currently displayed fragment, am I right?
  • Leem.fin
    Leem.fin over 12 years
    Ok, but I need a way to immediately get the currently displayed Fragment instance, not iteratively check through all fragments and then decide which fragment is now displayed on the screen. I think your answer needs my code to iteratively check each of my fragments, and find out the visible one ...
  • Thordax
    Thordax over 12 years
    Careful because you will get a ClassCastException if you try to get the fragment by doing what i said on my first post !
  • ramdroid
    ramdroid over 12 years
    Yes, but there could be more than one fragment visible at a time. So there is nothing like the "only active fragment"....
  • Leem.fin
    Leem.fin over 12 years
    Well, I really don't get your point, I mean I need a way to immediately get the currently displayed Fragment instance, not iteratively check through all fragments and then decide which fragment is now displayed on the screen.
  • Leem.fin
    Leem.fin over 12 years
    Ok, even there are several fragments displayed, I still need a way to get them... and a way which is better than iteratively check each of my fragments . I am concern on "get them" a method like getDisplayedFragment(), but not sure is there such method in Android
  • ramdroid
    ramdroid over 12 years
    I don't know why this is a problem to you... You usually have only few fragments in an activity and it shouldn't really be a problem to check them if they are visible or not.
  • loeschg
    loeschg over 10 years
    I'm fairly sure this technique won't work for Fragments used with a ViewPager, as they're not added by tag. Just tossing that out there.
  • TrtG
    TrtG over 10 years
    wouldn't that give a NPE if the fragment has never been displayed yet?
  • cprcrack
    cprcrack over 10 years
    This only seems to work when you call addToBackStack(tag), but what if you don't wan't to add the fragment to the back stack?
  • cprcrack
    cprcrack over 10 years
    fragment can be null in certain scenarios, such as when you pop the back stack. So better use if (fragment != null && fragment.isVisible()).
  • Admin
    Admin over 10 years
    This only works if your tag happens to be the same as the back stack name, which seems like it'd be unusual.
  • kehers
    kehers almost 10 years
    You should check to be sure count > 0 so that get(count-1) doesn't throw an IndexOutofBoundsException
  • Kevin Lam
    Kevin Lam almost 10 years
    What happens if you added 5 fragments in the same transaction?
  • ShortFuse
    ShortFuse almost 10 years
    Exactly what I was looking for when dealing with onBackPressed() after screen rotation with a Navigation Drawer. Thanks for coming back to share this.
  • JacksOnF1re
    JacksOnF1re almost 10 years
    If your phone is turned of isVisible will return false. Therefore this method does not indicates correct if fragment is the stack top one.
  • JacksOnF1re
    JacksOnF1re almost 10 years
    It is maybe nice to say that if you call addToBackStack(null) for some Fragment where you do not need a name, the method getName() can return null and you get a NPE. @ dpk, docu says: Get the name that was supplied to FragmentTransaction.addToBackStack(String) when creating this entry. Also ,add a null check if EntryCount is 0 and you try to receive the top entry.
  • letroll
    letroll over 9 years
    method incomplete because it's possible there are not only one fragment visible
  • Michael Peterson
    Michael Peterson over 9 years
    Check if myFragment is null or not before checking if it is visible. if (myFragment != null && myFragment.isVisible()) { ... }
  • parvus
    parvus over 9 years
    Strangely enough, this was the only solution listed here that worked for me. At the same time, multiple fragments can have isVisible() == true, getView() != null. Plus, in my code getBackStackEntryCount is always zero. Even though I don't use menu's, isMenuVisible() is so far the only discriminant that seems to point reliably to the currently 'active' fragment. ty
  • Andrew Senner
    Andrew Senner about 9 years
    Doesn't findFragmentById iterate through all the fragments internally? :)
  • Răzvan Barbu
    Răzvan Barbu almost 9 years
    in case .getFragmentManager reports incompatible type, as it did in my case, it is because I was using the android.support.app.v4.Fragment, in which case the right method to use is getSupportFragmentManager
  • DeltaCap019
    DeltaCap019 almost 9 years
    or you can use findFragmentByTag() in place of findFragmentById, if you have provided tag to fragment when adding it to fragmentManager.beginTransaction() .add(containerID, frag, fragmentTag) .addToBackStack(fragmentTag) .commit();
  • user798719
    user798719 almost 9 years
    fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT"); is used to set a TAG. But when I find the fragment later by TAG, it's null. Driving me nuts!
  • cafebabe1991
    cafebabe1991 over 8 years
    @tainy this wont give the fragment that was replaced but not added to the backstack .Right ? If yes, then can i get it using the tag argument ?
  • Pranav Mahajan
    Pranav Mahajan over 8 years
    If no fragment is visible, then fragmentManager.getFragments() will return NULL which will lead to NPE saying "Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a NULL object reference". Therefore, the for loop should be surrounded by a simple check: if (fragments != null)
  • Shayan Amani
    Shayan Amani over 8 years
    You need also to put the TAG in the addToBackStack(). take a look to @Dmitry_L answer for this case.
  • monad98
    monad98 over 8 years
    would you please explain more detail?
  • user2413972
    user2413972 about 8 years
    Yeah. And as for the treatment of "Back" you have not forgotten?
  • LEHO
    LEHO about 8 years
    The getFragments call won't give you the fragments the order they were added after you call popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) on it, and add more fragments.
  • Shivaraj Patil
    Shivaraj Patil almost 8 years
    What if more than one fragments are visible?
  • user1324887
    user1324887 almost 8 years
    @ShivarajPatil, In case of ActionBar more than 1 fragment is visiable, Did you find a solution?
  • Shivaraj Patil
    Shivaraj Patil almost 8 years
    '@user1324887 nop but what you can do is instead of returning a single fragment inside loop, add fragments to a list like List of visible fragments and return that list & go through each of them may be. Not perfect solution & I have not tested this.
  • HungNM2
    HungNM2 over 7 years
    if activity have more than one Fragment visible, your way is wrong. For example: ViewPager with Fragments. as I known getBackStackEntryCount() return number of Transaction, not number of fragment
  • Stumi
    Stumi over 7 years
    Unfortunately, this is not always true, the getSupportFragmentManager().getFragments() gives you back a list but that can hold null values, if the latest fragment just been popped from the backstack. Eq: If you check with your way inside the onBackStackChanged() method and you call the popBackStack() somewhere , then the mCurrentFragment will be null.
  • angryITguy
    angryITguy about 7 years
    Why is everyone upvoting this answer ? Sure, it's a nice bit of code but doesn't answer the question to get a specific fragment by tag.. BUT Asker wants the currently displayed fragment, which means he doesn't know which fragment is displayed. Yes, there may be multiple fragments, but reading the question infers only 1 fragment is displayed on the UI.... Sorry had to downvote because it doesn't answer the question context.
  • angryITguy
    angryITguy about 7 years
    Technically this should be marked as answer based on the question. Asker wants currently displayed fragment, not knowing which fragment it is. Other answers keep getting fragments by tag
  • malli
    malli over 6 years
    How can we use eventbus in this scenario??can you please share me one example.
  • Tim
    Tim over 6 years
    how is that reactive? You use an observable but it will only emit once
  • Peterstev Uremgba
    Peterstev Uremgba about 6 years
    And it's Just an overkill. A simple enhanced forloop would do just the same, maybe even faster.
  • Ajit Kumar Dubey
    Ajit Kumar Dubey about 6 years
    Suppose I have 10 Fragment then I need to write multiple line of code for checking which fragment is active. is there any best way to find the which fragment is active now without checking and typecasting multiple times.
  • AndroidLover
    AndroidLover almost 6 years
    using reactive stream for just stream api is not that smart , in fact like they said it is an overkill use the steam Java8 api if you want to treat the list as a stream and apply the filter api
  • Pritesh Vishwakarma
    Pritesh Vishwakarma over 5 years
    MainFragment myFragment = (MainFragment)getSupportFragmentManager().findFragmentById(R‌​.id.frame_layout); if (myFragment != null && myFragment.isVisible()) { Log.d(TAG,"myFragment is opened"); } else { Log.d(TAG,"myFragment is not opened and null"); } @AjitKumarDubey try this , with the help of this you dont have to keep track of every fragment tag. instead, use findFragmentById to find fragment and cast with class name and you can have condition for checking every fragment.
  • RustamG
    RustamG over 5 years
    You should check fragManager.getFragments().size() instead of getBackStackEntryCount() as they are not necessarily equal (which is my case). Otherwise you can get crash with IndexOutOfBoundsException
  • Farid
    Farid about 5 years
    @AndrewSenner, he means he didn't want to do it explicitly :)
  • ibit
    ibit about 5 years
    Works on API 26 and up only
  • Nativ
    Nativ about 5 years
    @Stumi Thanks for this information. Yep, sounds like one of many weird life cycle problems in Android.
  • HendraWD
    HendraWD about 5 years
    @ibit what do you mean with works on API 26 and up only? I tried on emulator API 19 working fine.
  • ibit
    ibit about 5 years
    @HendraWD you are correct! I was referring to the function in the frameworks getFragments() function, which is API 26 and up.
  • TheRealChx101
    TheRealChx101 almost 5 years
    This will not work well if you want to have a value returned
  • David García Bodego
    David García Bodego over 4 years
    Welcome to SO! When you post an answer, even if it is right, try to comment it a little bit. In this case, with another 41 answer, you should exposed Pros and Cons of your P.O.V.
  • Saddan
    Saddan over 4 years
    Thank you david , I appreciate your suggestion
  • Jetwiz
    Jetwiz over 4 years
    take care. If before you dont have any fragment stack, it can cause empty exception!
  • Blundell
    Blundell over 4 years
    so so close! :-)
  • IgorGanapolsky
    IgorGanapolsky about 4 years
    This doesn't compile
  • IgorGanapolsky
    IgorGanapolsky about 4 years
    We use Jetpack Navigation library
  • Cory Roy
    Cory Roy about 4 years
    It would only compile if you had properly setup AndroidX navigation and somehow called your navHost your_navhost.
  • coolcool1994
    coolcool1994 about 4 years
    This doesn't work? java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment cannot be cast to Fragment
  • coolcool1994
    coolcool1994 about 4 years
    Correct way is: supportFragmentManager.fragments.last()?.getChildFragmentMan‌​ager()?.getFragments‌​()?.get(0)
  • Kishan Solanki
    Kishan Solanki almost 4 years
    Try to navigate between fragments and press back, app will be crashed!
  • Michael Abyzov
    Michael Abyzov over 3 years
    I'm not sure, but maybe to get currently displayed fragment firstOrNull( ) instead of lastOrNull( ) should be used?
  • RodParedes
    RodParedes over 2 years
    This only works when you use fragmentManager.replace().commit() and not when is used fragmentmanager.add().hide().show().commit() right?
  • Torima
    Torima about 2 years
    This returns destination, not a fragment. If you need fragment you can use: supportFragmentManager.findFragmentById(R.id.your_nav_graph_‌​container).childFrag‌​mentManager.primaryN‌​avigationFragment
  • George Ampartzidis
    George Ampartzidis about 2 years
    This is the only answer I could use in my case! Thank you!