How do I get the currently displayed fragment?
Asked Answered
T

58

537

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?

Thither answered 15/2, 2012 at 13:49 Comment(3)
Related - https://mcmap.net/q/57287/-retrieve-a-fragment-from-a-viewpagerAlbertina
Possible duplicate of Get the current fragment objectInclinometer
navController.currentDestination?.idOrlon
M
510

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

Macerate answered 15/2, 2012 at 14:22 Comment(12)
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 ...Thither
Yes, but there could be more than one fragment visible at a time. So there is nothing like the "only active fragment"....Macerate
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 AndroidThither
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.Macerate
wouldn't that give a NPE if the fragment has never been displayed yet?Jabin
If your phone is turned of isVisible will return false. Therefore this method does not indicates correct if fragment is the stack top one.Ratib
Check if myFragment is null or not before checking if it is visible. if (myFragment != null && myFragment.isVisible()) { ... }Malocclusion
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!Espagnole
You need also to put the TAG in the addToBackStack(). take a look to @Dmitry_L answer for this case.Caryophyllaceous
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.Smitten
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.Bareback
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.Lyrist
M
454

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.

Mitchum answered 5/7, 2014 at 17:54 Comment(5)
Exactly what I was looking for when dealing with onBackPressed() after screen rotation with a Navigation Drawer. Thanks for coming back to share this.Ladylove
Doesn't findFragmentById iterate through all the fragments internally? :)Gonzalogoo
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 getSupportFragmentManagerInfelicity
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();Kaminsky
@AndrewSenner, he means he didn't want to do it explicitly :)Mcmullin
S
184

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;
}
Steelwork answered 10/10, 2013 at 21:35 Comment(7)
fragment can be null in certain scenarios, such as when you pop the back stack. So better use if (fragment != null && fragment.isVisible()).Chatter
method incomplete because it's possible there are not only one fragment visibleTraylor
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)Amari
What if more than one fragments are visible?Pyles
@ShivarajPatil, In case of ActionBar more than 1 fragment is visiable, Did you find a solution?Insufficiency
'@Insufficiency 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.Pyles
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 tagSmitten
M
83

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);
}
Mincemeat answered 21/3, 2013 at 9:24 Comment(5)
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.Overbid
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?Chatter
This only works if your tag happens to be the same as the back stack name, which seems like it'd be unusual.Telfer
What happens if you added 5 fragments in the same transaction?Argentina
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.Ratib
L
41

Kotlin way;

val currentFragment = supportFragmentManager.fragments.last()
Langbehn answered 22/2, 2019 at 14:42 Comment(6)
Works on API 26 and up onlyBreechblock
@Breechblock what do you mean with works on API 26 and up only? I tried on emulator API 19 working fine.Speak
@Speak you are correct! I was referring to the function in the frameworks getFragments() function, which is API 26 and up.Breechblock
take care. If before you dont have any fragment stack, it can cause empty exception!Spinning
This doesn't work? java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment cannot be cast to FragmentSpeculation
Correct way is: supportFragmentManager.fragments.last()?.getChildFragmentManager()?.getFragments()?.get(0)Speculation
H
23

What I am using to find current displaying fragment is in below code. It is simple and it works for me by now. It runs in the activity which holds the fragments

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
Hemicycle answered 9/6, 2014 at 1:51 Comment(5)
You should check to be sure count > 0 so that get(count-1) doesn't throw an IndexOutofBoundsExceptionStandridge
@Hemicycle 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 ?Terenceterencio
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.Bacolod
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 fragmentUnknow
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 IndexOutOfBoundsExceptionJoost
G
15

To return current Fragment destination and you are using the AndroidX Navigation:

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

To return current Fragment name, you can use the following instead:

val currentFragment = supportFragmentManager.findFragmentById(R.id. your_navhost)?.childFragmentManager?.primaryNavigationFragment

For more info on this navigation component: https://developer.android.com/guide/navigation/navigation-getting-started

Ghibelline answered 10/3, 2020 at 23:56 Comment(3)
This doesn't compileMise
It would only compile if you had properly setup AndroidX navigation and somehow called your navHost your_navhost.Ghibelline
This returns destination, not a fragment. If you need fragment you can use: supportFragmentManager.findFragmentById(R.id.your_nav_graph_container).childFragmentManager.primaryNavigationFragmentTrippet
E
13

My method is based on try / catch like this :

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

But there may be a better way ...

Ecg answered 15/2, 2012 at 13:54 Comment(7)
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.Thither
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);Ecg
If I have multiple fragments, can I use one tag for all the fragments when call .replace(...) ?Thither
Yes, no problem, use this code : fragmentTransaction.replace(R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); and it may go well.Ecg
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?Thither
Careful because you will get a ClassCastException if you try to get the fragment by doing what i said on my first post !Ecg
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.Thither
C
13

The reactive way:

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });
Catharina answered 26/4, 2016 at 15:46 Comment(3)
how is that reactive? You use an observable but it will only emit oncePreconscious
And it's Just an overkill. A simple enhanced forloop would do just the same, maybe even faster.Hemicrania
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 apiBysshe
A
11

Well, this question got lots of views and attention but still did not contained the easiest solution from my end - to use getFragments().

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);
Apterous answered 16/5, 2016 at 15:6 Comment(2)
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.Structure
@Structure Thanks for this information. Yep, sounds like one of many weird life cycle problems in Android.Apterous
S
9

You can query which fragment is loaded into your Activities content frame, and retrieve the fragment class, or fragment 'simple name' (as a string).

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

Usage:

Log.d(TAG, getCurrentFragment());

Outputs:

D/MainActivity: FragOne
Snivel answered 27/5, 2018 at 16:3 Comment(0)
K
9

If get here and you are using Kotlin:

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

R.id.fragment_container is the id where the fragment is presenting on their activity

Or if you want a nicer solution:

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

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}
Kris answered 13/11, 2018 at 0:20 Comment(1)
This only works when you use fragmentManager.replace().commit() and not when is used fragmentmanager.add().hide().show().commit() right?Macrophysics
S
8

It's a bit late, But for anyone who is interested : If you know the index of the your desired fragment in FragmentManager just get a reference to it and check for isMenuVisible() function! here :

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

If true Its visible to user and so on!

Swarthy answered 27/6, 2014 at 6:59 Comment(1)
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. tyUpstretched
C
8

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
}
Christal answered 9/12, 2015 at 8:5 Comment(0)
E
6

There's a method called findFragmentById() in SupportFragmentManager. I use it in the activity container like :

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

That's how to get your current Fragment. If you have custom Fragment and need to check what Fragment it is, I normally use instanceof :

if (currentFragment() instanceof MyFrag){
    // Do something here
}
Esmaria answered 10/3, 2017 at 2:6 Comment(0)
S
6

None of the above 30 answers fully worked for me. But here is the answer that worked:

Using Kotlin, when using Navigation Component:

fun currentVisibleFragment(): Fragment? {
    return supportFragmentManager.fragments.first()?.getChildFragmentManager()?.getFragments()?.get(0)
}
Speculation answered 3/5, 2020 at 16:51 Comment(1)
This is the only answer I could use in my case! Thank you!Iguanodon
H
6

This should work -

val visibleFragment = supportFragmentManager.fragments.findLast { fgm -> fgm.isVisible }
Timber.d("backStackIterator: visibleFragment: $visibleFragment")
Helfand answered 16/6, 2021 at 12:8 Comment(0)
P
5

Inspired by Tainy's answer, here is my two cents. Little modified from most other implementations.

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

Replace "myActivity" with "this" if it is your current activity or use reference to your activity.

Pickwickian answered 14/6, 2016 at 20:20 Comment(0)
S
5

This is simple way to get current fragment..

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);
    }
  }
});
Seemly answered 8/9, 2017 at 4:46 Comment(0)
M
5

Checkout this solution. It worked for me to get the current 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");
        }
Melson answered 27/9, 2018 at 4:24 Comment(0)
S
5

it's so simple, not that much code you need to write yourFragment.isAdded() or yourFragment.isVisible();

I prefer isAdded(),both of them return boolean value use it in if condition and must initialize your fragment in onCreate() otherwise you will get null point exception.

Spectrum answered 20/10, 2019 at 11:45 Comment(2)
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.Lindsylindy
Thank you david , I appreciate your suggestionSpectrum
V
4

Sev's answer works for when you hit the back button or otherwise change the backstack.

I did something slightly different, though. I have a backstack change listener setup on a base Fragment and its derived fragments and this code is in the 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
}
Versieversification answered 12/6, 2015 at 15:6 Comment(0)
S
4

Easy way to do that :

Fragment fr=getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String fragmentName = fr.getClass().getSimpleName();
Sabian answered 11/2, 2020 at 16:33 Comment(0)
L
4

I had to do this very recently

public Fragment getCurrentFragment() {
     return fragmentManager.findFragmentById(R.id.container);
}

and finaly i got last fragment on this container.

Lampert answered 31/1, 2021 at 8:32 Comment(0)
T
3
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");
}
Truck answered 13/3, 2014 at 16:7 Comment(0)
T
3

If you are getting the current instance of Fragment from the parent activity you can just

findFragmentByID(R.id.container);

This actually get's the current instance of fragment that's populated on the view. I had the same issue. I had to load the same fragment twice keeping one on backstack.

The following method doesn't work. It just gets a Fragment that has the tag. Don't waste your time on this method. I am sure it has it's uses but to get the most recent version of the same Fragment is not one of them.

findFragmentByTag()
Triclinic answered 29/10, 2015 at 21:8 Comment(0)
H
3

Kotlin safer way than exposed here

supportFragmentManager.fragments.lastOrNull()?.let { currentFragment ->
               
      //Do something here
 }
Husband answered 23/7, 2020 at 23:17 Comment(1)
I'm not sure, but maybe to get currently displayed fragment firstOrNull( ) instead of lastOrNull( ) should be used?Doro
U
2

This is work for me. I hope this will hepl someone.

FragmentManager fragmentManager = this.getSupportFragmentManager();  
        String tag = fragmentManager
                    .getBackStackEntryAt(
                    fragmentManager
                    .getBackStackEntryCount() - 1)
                    .getName();
              Log.d("This is your Top Fragment name: ", ""+tag);
Unexceptionable answered 16/12, 2014 at 19:23 Comment(0)
A
2

I found findFragmentByTag isn't that convenient. If you have String currentFragmentTag in your Activity or parent Fragment, you need to save it in onSaveInstanceState and restore it in onCreate. Even if you do so, when the Activity recreated, onAttachFragment will called before onCreate, so you can't use currentFragmentTag in onAttachFragment(eg. update some views based on currentFragmentTag), because it's might not yet restored.

I use the following code:

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

The document of FragmentManager state that

The order of the fragments in the list is the order in which they were added or attached.

When you need to do stuff based on current fragment type, just use getCurrentFragment() instance of MyFragment instead of currentFragmentTag.equals("my_fragment_tag").

Note that getCurrentFragment() in onAttachFragment will not get the attaching Fragment, but the previous attached one.

Anlage answered 16/9, 2018 at 5:6 Comment(0)
R
2
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

Well, I guess this is the most straight forward answer to this question. I hope this helps.

Ruder answered 11/6, 2019 at 15:51 Comment(0)
A
2

You can do it very easily also with a URL in logcat which will redirect you to the source code of current fragment source code. First, you need to add an OnBackStackChangedListener in host activity like -

activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);

And the OnBackStackChangedListener implementation is -

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

And the getStackTopName() method is -

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;
}
Austro answered 9/12, 2019 at 5:18 Comment(0)
H
2
  SupportFragmentManager.BeginTransaction().Replace(Resource.Id.patientFrameHome, test, "Test").CommitAllowingStateLoss();  

var fragment = SupportFragmentManager.FindFragmentByTag("Test") as V4Fragment;

  if (fragment == null && fragment.IsVisiable is true)
{
}
Hardware answered 15/7, 2020 at 7:36 Comment(0)
Y
1

In the main activity, the onAttachFragment(Fragment fragment) method is called when a new fragment is attached to the activity. In this method, you can get the instance of the current fragment. However, the onAttachFragment(Fragment fragment) method is not called when a fragment is popped off the back stack, ie, when the back button is pressed to get the top fragment on top of the stack. I am still looking for a callback method that is triggered in the main activity when a fragment becomes visible inside the activity.

Yila answered 16/4, 2013 at 4:37 Comment(2)
so so close! :-)Lucretialucretius
We use Jetpack Navigation libraryMise
C
1

In case of scrolled fragments, when your use instance of ViewPager class, suppose mVeiwPager, you can call mViewPager.getCurrentItem() for get current fragment int number.

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)
//         ...
          }
Cat answered 5/11, 2017 at 21:40 Comment(0)
M
1

I had to do this very recently and none of the answers here really suited this scenario.

If you are confident that only one fragment will be visible (full-screen), so really want to find what's at the top of the backstack. For instance, as a Kotlin for 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)
        }
    }
}

And use it like:

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

        setVisibilityChangeListener(this::class.java) { visible -> 
            // Do stuff
        }
    }
}
Meek answered 13/3, 2019 at 11:37 Comment(0)
H
1

Here is a Kotlin solution:

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

Simplified way:

with ( this.getSupportFragmentManager() ) {
    if ( getBackStackEntryCount()>0 ) {
        var fgmt = fragments[getBackStackEntryCount()-1]
        if ( fgmt is FgmtClassName ) {
            (fgmt as FgmtClassName).doSth()
        }
    }
}
Husbandry answered 16/9, 2019 at 13:45 Comment(1)
Try to navigate between fragments and press back, app will be crashed!Jacquerie
M
1

If you are using Jetpack Navigation library:

val currentFragment = defaultNavigator.currentDestination

Mise answered 17/4, 2020 at 18:30 Comment(0)
L
1

I just needed to do this, if you have access to the nav controller, you can obtain the current fragment from the back stack easily:

// current fragments label/title:
navController.backStack.last.destination.label

// current fragments name:
navController.backStack.last.destination.displayName

To get access to nav controller (replace with correct name):

val navController = findNavController(R.id.nav_host_fragment_activity_main)
Locality answered 8/1, 2022 at 4:18 Comment(2)
for my version navController.backQueue worked the same wayConti
thanks for this . i was trying with getSupportFragmentManager and it wasnt as easy as this one.Conti
K
1

In androidx.fragment:fragment-ktx:1.4 there is a new way how can we get recently added fragment to the container. If you using FragmentContainerView as a container for yours fragments it will be easy:

val fragmentContainer: FragmentContainerView = ...
val currentFragment: Fragment = fragmentContainer.getFragment()
Kenweigh answered 8/2, 2022 at 8:36 Comment(0)
E
1

You must use a recursive function to find the current fragment because the fragment itself may have child fragments.

private fun findLastFragment(fragment: Fragment?): Fragment? {
    val mFragment = fragment?.childFragmentManager?.fragments?.lastOrNull()
    return if (mFragment == null) {
        fragment
    } else {
        findLastFragment(mFragment)
    }
}

for use the above function for example call

findLastFragment(activity.supportFragmentManager.fragments.lastOrNull())
Engedi answered 10/4, 2023 at 11:26 Comment(0)
I
0

If you use the Support library v13 than this issue is fixed and you should simply override:

@Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
    // TODO Auto-generated method stub
    super.setUserVisibleHint(isVisibleToUser);
}

The thing is, you can't mix the two because the fragment is not compatible with the Fragment Class of the of the version 4.

If you are not and you are using the V4 support lib, Override the setPrimaryItem method to your FragmentStatePagerAdapter.

I was using this to update the Actionbat title in big lists.

Intravasation answered 15/10, 2013 at 14:6 Comment(0)
D
0

Maybe the simplest way is:

public MyFragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    for(Fragment fragment : fragments){
        if(fragment != null && fragment.getUserVisibleHint())
            return (MyFragment)fragment;
    }
    return null;
}

It worked for me

Dessiatine answered 7/6, 2014 at 18:44 Comment(0)
S
0

Using an event bus (like Otto, EventBus or an RxJava Bus) is especially handy in these situations.

While this approach doesn't necessarily hand you down the currently visible fragment as an object (though that too can be done but it leads to a longer call chain), it allows you execute actions on the currently visible fragment (which is usually what you want to do knowing the currently visible fragment).

  1. make sure you respect the fragment lifecycle and register/unregister the event bus at the appropriate times
  2. at the point where you need to know the currently visible fragment and execute a set of actions. shoot an event out with the event bus.

all visible fragments that have registered with the bus will execute the necessary action.

Stuckup answered 15/7, 2015 at 22:41 Comment(3)
would you please explain more detail?Byelaw
How can we use eventbus in this scenario??can you please share me one example.Otilia
This will not work well if you want to have a value returnedRennarennane
C
0

I ran into a similar problem, where I wanted to know what fragment was last displayed when the back key was pressed. I used a very simple solution that worked for me. Each time I open a fragment, in the onCreate() method, I set a variable in my singleton (replace "myFragment" with the name of your fragment)

MySingleton.currentFragment = myFragment.class;

The variable is declared in the singleton as

public static Class currentFragment = null; 

Then in the onBackPressed() I check

    if (MySingleton.currentFragment == myFragment.class){
        // do something
        return;
    }
    super.onBackPressed();

Make sure to call the super.onBackPressed(); after the "return", otherwise the app will process the back key, which in my case caused the app to terminate.

Credits answered 22/8, 2015 at 21:48 Comment(0)
J
0

A bit strange but I looked at FragmentManager$FragmentManagerImpl and the following works for me:

public static Fragment getActiveFragment(Activity activity, int index)
{
    Bundle bundle = new Bundle();
    String key = "i";
    bundle.putInt(key,index);
    Fragment fragment=null;
    try
    {
        fragment = activity.getFragmentManager().getFragment(bundle, key);
    } catch(Exception e){}
    return fragment;
}

to get the first active fragment use 0 as the index

Jezabella answered 21/9, 2015 at 13:56 Comment(0)
L
0
public Fragment getVisibleFragment() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    if(fragments != null) {
        for (Fragment fragment : fragments) {
            if (fragment != null && fragment.isVisible())
                return fragment;
        }
    }
    return null;
}

This works for me. You need to perform a null check before you iterate through the fragments list. There could be a scenario that no fragments are loaded on the stack.

The returning fragment can be compared with the fragment you want to put on the stack.

Lanai answered 6/10, 2015 at 13:30 Comment(0)
C
0

Please try this method .....

private Fragment getCurrentFragment(){
    FragmentManager fragmentManager = getSupportFragmentManager();
    String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();
    Fragment currentFragment = getSupportFragmentManager()
.findFragmentByTag(fragmentTag);
    return currentFragment;
}
Consistency answered 27/10, 2015 at 6:18 Comment(0)
D
0

You can get current fragment by using following code

FragmentClass f = (FragmentClass)viewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem());
Daisey answered 6/12, 2015 at 19:10 Comment(0)
B
0

You can add a class variable selectedFragment, and every time you change the fragment you update the variable.

public Fragment selectedFragment;
public void changeFragment(Fragment newFragment){
    FragmentManager fragMgr = getSupportFragmentManager();
    FragmentTransaction fragTrans = fragMgr.beginTransaction();
    fragTrans.replace(android.R.id.content, newFragment);
    fragTrans.addToBackStack(null);
    fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    fragTrans.commit();
    //here you update the variable
    selectedFragment = newFragment;
}

then you can use selectedFragment wherever you want

Behring answered 9/12, 2015 at 13:37 Comment(1)
Yeah. And as for the treatment of "Back" you have not forgotten?Kinnon
P
0

Hello I know this is an very old issue, but I would like to share my own solution..

In order to get the browsed fragment list by the user, I created a helper class:

public class MyHelperClass{

    private static ArrayList<Fragment> listFragment = new ArrayList<>();

    public static void addFragment(Fragment f){
        if(!existFragment(f)) {
            listFragment.add(f);
        }
    }
    public static void removeFragment(){
        if(listFragment.size()>0)
            listFragment.remove(listFragment.size()-1);
    }
    public static Fragment getCurrentFragment(){
        return listFragment.get(listFragment.size()-1);
    }
    public static int sizeFragments(){
        return listFragment.size();
    }
    private static Boolean existFragment(Fragment f){
        Boolean ret = false;
        for(Fragment fragment : listFragment){
            if (fragment.getClass() == f.getClass()){
                ret = true;
            }
        }
        return ret;
    }

And into the main Activity, I override onAttachFragment method

@Override
public void onAttachFragment(Fragment f) {
    super.onAttachFragment(f);

    MyHelperClass.addFragment(f);
}

and also, I override onBackPressed Method:

@Override
public void onBackPressed() {
        General.removeFragment();
        if(General.sizeFragments()>0){
            Fragment fragment = null;
            Class fragmentClass = General.getCurrentFragment().getClass();

            try {
                fragment = (Fragment) fragmentClass.newInstance();
                fragment.setArguments(General.getCurrentFragment().getArguments());
            } catch (Exception e) {
                e.printStackTrace();
            }

            fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
        }else{
            super.onBackPressed();
        }
}

so by this way you any time can get the active fragment with MyHelperClass.getCurrentFragment()

I hope this be helpful for anyone

regards

Pevzner answered 27/2, 2016 at 19:32 Comment(0)
I
0

well i think you want to see in which fragment u're in i guess there is a sollution i dont think its the best but it works First at all


you should create your parent fragment that it extends Fragment


public class Fragment2 extends Fragment {
    private static position;
    public static int getPosition() {
        return position;
    }

    public static void setPosition(int position) {
        FragmentSecondParent.position = position;
    }
}

Second

you should extend it in every fragment and in each write in onCreateView

setPosition(//your fragmentposition here)

Third


where you want to get the current fragment you should


write this

Fragment2 fragment= (Fragment2) getSupportFragmentManager()
    .findFragmentById(R.id.fragment_status);

int position = fragment.getPosition();
if(//position condition)
{
    //your code here
}
Inter answered 27/3, 2017 at 18:25 Comment(0)
V
0

this is the best way:

       android.app.Fragment currentFragment=getFragmentManager().findFragmentById(R.id.main_container);
            if(currentFragment!=null)
            {
                String[] currentFragmentName = currentFragment.toString().split("\\{");
                if (currentFragmentName[0].toString().equalsIgnoreCase("HomeSubjectFragment"))
                {
                    fragment = new HomeStagesFragment();
                    tx = getSupportFragmentManager().beginTransaction();
                    tx.replace(R.id.main_container, fragment);
                    tx.addToBackStack(null);
                    tx.commit();
                }
                else if(currentFragmentName[0].toString().equalsIgnoreCase("HomeStagesFragment"))
                {
                    new AlertDialog.Builder(this)
                            .setMessage("Are you sure you want to exit?")
                            .setCancelable(false)
                            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    finish();
                                }
                            })
                            .setNegativeButton("No", null)
                            .show();
                }

            }

dont forget to define this in header :

private Fragment fragment;
FragmentTransaction tx;
Vanna answered 12/7, 2017 at 9:2 Comment(0)
E
0

I also stuck on this point. What I finally did, just declared an array of Fragments:

private static PlaceholderFragment[] arrFrg;

(in my case it is PlaceholderFragment) and packed all thsess Fragemnts into this array without tagging :)

        public static PlaceholderFragment newInstance(int sectionNumber) {
            final PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            arrFrg[sectionNumber] = fragment;

            return fragment;
}

Then you can easily access the currently displayed Fragment:

arrFrg[mViewPager.getCurrentItem()];

I understand, this is probably not the best solution but it perfectly works for me :)

Exceptive answered 13/6, 2018 at 19:17 Comment(0)
V
0

In case you have nested fragments, like viewpagers inside viewpagers etc and you want to get all nested fragments.

Thanks and courtesy of Matt Mombrea answer a little tweaked version.

private List<Fragment> getVisibleFragments(List<Fragment> searchFragments, List<Fragment> visibleFragments) {
    if (searchFragments != null && searchFragments.size() > 0) {
        for (Fragment fragment : searchFragments) {
            List<Fragment> nestedFragments = new ArrayList<>();
            List<Fragment> childFMFragments = fragment.getChildFragmentManager().getFragments();
            List<Fragment> fmFragments = fragment.getFragmentManager().getFragments();
            fmFragments.retainAll(childFMFragments);
            nestedFragments.addAll(childFMFragments);
            nestedFragments.addAll(fmFragments);
            getVisibleFragments(nestedFragments, visibleFragments);
            if (fragment != null && fragment.isVisible()) {
                visibleFragments.add(fragment);
            }
        }
    }
    return visibleFragments;
}

And here is the usage:

List<Fragment> allVisibleFragments = getVisibleFragments(searchFragments, visibleFragments);

For example:

List<Fragment> visibleFragments = new ArrayList<>();
List<Fragment> searchFragments = MainActivity.this.getSupportFragmentManager().getFragments();
Toast.makeText(this, ""+getVisibleFragments(searchFragments, visibleFragments), Toast.LENGTH_LONG).show();
Valentinvalentina answered 8/4, 2019 at 22:42 Comment(0)
A
0

if getFragmentManager() not works then try with getSupportFragmentManager() and add a tag at the time of load fragment.

public void onBackPressed(){

    Fragment fragment=getSupportFragmentManager().findFragmentByTag(/*enter your tag*/);


    if(fragment!=null && fragment.isVisible())
    {
        //do your code here
    }
    else
    {
       //do your code here
    }

}
Allurement answered 5/7, 2019 at 11:20 Comment(0)
M
0

In Your Activity init your fragment before on create

    MyFragment myFragment = new MyFragment(); // add this
 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
........

then call the method to view your fragment

openFragment(this.myFragment);

Here is the method

(R.id.frame_container) is your fragment container id in xml file (Frame Layout)

 private void openFragment(final Fragment fragment)   {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.frame_container, fragment);
        transaction.commit();

    }

then in your activity, the Override method should be like

    public void onBackPressed() {
            if (myFragment.isVisible()) {
                myFragment.onBackPressed(this);
                return;
            }
            super.onBackPressed();
        }

then inside your fragment put this method

public  void onBackPressed(Activity activity) {
    Toast.makeText(activity, "Back Pressed inside Fragment", Toast.LENGTH_SHORT).show();
}
Mulct answered 8/9, 2021 at 11:17 Comment(0)
B
0

This is a simple solution I have Found. It will show all the fragment managed by navGraph

navHostFragment =
                supportFragmentManager.findFragmentById(R.id.nav_host_fragment_content_main) as NavHostFragment
            navController = navHostFragment.navController
    
            navGraph = navController.navInflater.inflate(R.navigation.nav_graph)
    
            val navView: BottomNavigationView = binding.navView
            navView.setupWithNavController(navController)
    
    
            navController.addOnDestinationChangedListener { controller, destination, arguments ->
                Log.e("HelloFragment", navController.currentDestination?.label.toString())
    
            }
Billen answered 20/5, 2023 at 11:51 Comment(0)
S
-1

Return the currently active primary navigation fragment for this FragmentManager.

public @Nullable Fragment getPrimaryNavigationFragment()      
Fragment fragment = fragmentManager.getPrimaryNavigationFragment();  
    
Sequence answered 3/1, 2022 at 12:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.