181

In my main.xml I have

  <FrameLayout
        android:id="@+id/frameTitle"
        android:padding="5dp"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:background="@drawable/title_bg">
            <fragment
              android:name="com.fragment.TitleFragment"
              android:id="@+id/fragmentTag"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content" />

  </FrameLayout>

And I'm setting fragment object like this

FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment newFragment = new FragmentType1();
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");

// fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

It is setting different types of Fragment objects (FragmentType2,FragmentType3,...) at different time. Now at some point of time I need to identify which object is currently there.

In short I need to do something like this:

Fragment currentFragment = //what is the way to get current fragment object in FrameLayout R.id.frameTitle

I tried the following

TitleFragment titleFragmentById = (TitleFragment) fragmentManager.findFragmentById(R.id.frameTitle);

and

    TitleFragment titleFragmentByTag = (TitleFragment) fragmentManager.findFragmentByTag("fragmentTag");

But both the objects (titleFragmentById and titleFragmentByTag ) are null
Did I miss something?
I'm using Compatibility Package, r3 and developing for API level 7.

findFragmentById() and findFragmentByTag() will work if we have set fragment using fragmentTransaction.replace or fragmentTransaction.add, but will return null if we have set the object at xml (like what I have done in my main.xml). I think I'm missing something in my XML files.

Léo Lam
  • 3,870
  • 4
  • 34
  • 44
Labeeb Panampullan
  • 34,521
  • 28
  • 94
  • 112

19 Answers19

269

Now at some point of time I need to identify which object is currently there

Call findFragmentById() on FragmentManager and determine which fragment is in your R.id.frameTitle container.

If you are using the androidx edition of Fragment — as you should in modern apps — , use getSupportFragmentManager() on your FragmentActivity/AppCompatActivity instead of getFragmentManager()

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 2
    Thanks for your response. It will work if we have set fragment using `fragmentTransaction.replac`e or `fragmentTransaction.add` but will not get if we have set it at xml. See my edit 2 – Labeeb Panampullan Aug 05 '11 at 06:09
  • 10
    @Labeeb P: You cannot modify fragments declared in the layout resources. – CommonsWare Aug 05 '11 at 10:22
  • Creating a class to hold the currently visible tab/ fragment will work also, I jjust tried that. Hope there are no failures. – Skynet Dec 04 '13 at 07:37
  • @CommonsWare `findFragmentByTag` returning null in case of `ActionBar` Tabs. In my `Activity` which is extending `ActionBarActivity` i'm first adding tabs to `ActionBar` and then finding it! – Muhammad Babar May 27 '14 at 07:03
  • @CommonsWare inside my `onTabSelected` i have also tried `executePendingTransactions()` by still no luck. Could you please help! – Muhammad Babar May 27 '14 at 07:04
  • @CommonsWare This worked when i tried to find fragment from `onResume()`. Is it possible to do this from `onCreate()`? – Muhammad Babar May 27 '14 at 07:09
  • 1
    @MuhammadBabar: You can try `executePendingTransactions()` on `FragmentManager` after calling `commit()` on the transaction, though I have not tried this. Or you can use `setContentView()` to use a layout file with a `` tag. Either of those happen synchronously, and so the fragment will exist within the `onCreate()` call itself where you used `executePendingTransaction()` or `setContentView()`. Otherwise, an ordinary `FragmentTransaction` is processed asynchronously, and it will not have even begun by the time `onCreate()` ends. – CommonsWare May 27 '14 at 17:59
  • @CommonsWare I knew this would have worked in normal scenario. but i'm using ActionBarTabs and inside `onTabselected()` of `TabListener` fragment is being **just** added we can't call commit because system calls it for us else it results in *exception*. – Muhammad Babar May 28 '14 at 04:58
  • Though i did handle the scenario by moving the call to `onResume()` and used a `boolean` flag to handle but still curious to know the work around other way. Thanks for the help :) – Muhammad Babar May 28 '14 at 04:59
  • I just went through a bunch of this - seems a major confusion happens because findFragmentByTag() does not use the Tag presented by the BackStackEntry ( sort of an assumption) The two tags are specified independently - the findFragmentByTag() uses the getTag() on the fragment if you want to use the tag in the entry to find the fragment you have to separately specify it. It will not default to the tag of the fragment referenced by the entry if left as null. – peterk Sep 19 '15 at 04:26
  • When I call this I still get null – IntoTheDeep Jul 01 '16 at 08:19
  • How to determine if a fragment is still in backstack? – eC Droid Aug 08 '17 at 10:49
  • @eCDroid: I do not think that there is a direct way to do that, sorry. You can ask the `FragmentManager` about back stack entries, but the details that you get back do not include the `Fragment` itself. If you do a good job with the names and IDs, you might be able to determine the fragment for a `BackStackEntry` by those pieces of data, though. – CommonsWare Aug 08 '17 at 11:12
  • Using tags (For fragments) and name (for backstack state) i still didn't find any api that can tell if a fragment is in the back stack. The only viable solution that worked is to do like this `Fragment fragment = manager.findFragmentByTag(name); return fragment != null;` – eC Droid Aug 08 '17 at 11:32
  • @eCDroid: `getBackStackEntryCount()` and `getBackStackEntry()` on `FragmentManager` will tell you what is on that manager's back stack. `findFragmentByTag()` has nothing to do with the back stack, though depending on your use of fragments it might work for your specific scenario. – CommonsWare Aug 08 '17 at 11:38
  • Official doc of `findFragmentByTag` is `Finds a fragment that was identified by the given tag either when inflated from XML or as supplied when added in a transaction. This first searches through fragments that are currently added to the manager's activity; if no such fragment is found, then all fragments currently on the back stack are searched.` note this **if no such fragment is found, then all fragments currently on the back stack are searched** – eC Droid Aug 08 '17 at 12:36
  • While getBackStackEntry() worked with index not id or tag. So i have to iterate the whole fragment manager and do is instanceOf with class name. Which one you suggest. – eC Droid Aug 08 '17 at 12:38
  • @eCDroid: My point is that `findFragmentByTag()` does not indicate if the fragment is on the back stack. It simply indicates if the fragment is known by the manager, which includes fragments not on the back stack. Your point regarding `instanceof` does not make sense to me, as there is nothing in the `BackStackEntry` that contains your `Fragment`. My suggestion is that you ask a separate Stack Overflow question. – CommonsWare Aug 08 '17 at 12:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/151393/discussion-between-ec-droid-and-commonsware). – eC Droid Aug 08 '17 at 13:02
  • Okay finally this `public boolean isBackStackExists(String tag) { FragmentManager manager = ((Activity) context).getFragmentManager(); for(int i = 0; i < manager.getBackStackEntryCount(); i++) { String backStackTag = manager.getBackStackEntryAt(i).getName(); if(backStackTag.equals(tag)) { return true; } } return false; }` works for me. I have to use same tag for fragment and backstack. – eC Droid Aug 08 '17 at 15:49
116

Try this,

Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);

this will give u the current fragment, then you may compare it to the fragment class and do your stuffs.

    if (currentFragment instanceof NameOfYourFragmentClass) {
     Log.v(TAG, "find the current fragment");
  }
Alan Nelson
  • 1,129
  • 2
  • 11
  • 27
Hammer
  • 8,538
  • 12
  • 44
  • 75
38

I think you can use onAttachFragment event may be useful to catch which fragment is active.

@Override
public void onAttachFragment(Fragment fragment) {
    // TODO Auto-generated method stub
    super.onAttachFragment(fragment);

    Toast.makeText(getApplicationContext(), String.valueOf(fragment.getId()), Toast.LENGTH_SHORT).show();

}
Cat
  • 66,919
  • 24
  • 133
  • 141
Hede Hodo
  • 397
  • 3
  • 3
  • 3
    i can able to get which fragment i am attached. My dought is when i change the orientation then i need to display the same view not another view so how to do this. – Androi Developer Apr 03 '13 at 14:00
  • 7
    This doesn't work because it doesn't update the active fragment when you go back. – Justin Feb 26 '14 at 17:26
  • 1
    @Justin so we just need to use onDetach also with a weakreference list – letroll Feb 04 '15 at 14:18
13

I think you should do:

Fragment currentFragment = fragmentManager.findFragmentByTag("fragmentTag");

The reason is because you set the tag "fragmentTag" to the last fragment you have added (when you called replace).

Niqo
  • 1,072
  • 10
  • 20
  • Thanks I have corrected it. Its a typo mistake while writing this question. It will work if we have set fragment using `fragmentTransaction.replac`e or `fragmentTransaction.add` but will not get if we have set it at xml. See my edit 2 – Labeeb Panampullan Aug 05 '11 at 06:08
  • 2
    doesn't this solution means that you have to put same tag for multiple fragments? otherwise how would you know `fragmentTag` is the tag for the current fragment? – Thupten Jun 26 '13 at 19:39
12

You can get the list of the fragments and look to the last one.

    FragmentManager fm = getSupportFragmentManager();
    List<Fragment> fragments = fm.getFragments();
    Fragment lastFragment = fragments.get(fragments.size() - 1);

But sometimes (when you navigate back) list size remains same but some of the last elements are null. So in the list I iterated to the last not null fragment and used it.

    FragmentManager fm = getSupportFragmentManager();
    if (fm != null) {
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            for(int i = fragments.size() - 1; i >= 0; i--){
                Fragment fragment = fragments.get(i);
                if(fragment != null) {
                    // found the current fragment

                    // if you want to check for specific fragment class
                    if(fragment instanceof YourFragmentClass) {
                        // do something
                    }
                    break;
                }
            }
        }
    }
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
eluleci
  • 3,489
  • 1
  • 26
  • 24
  • 3
    Don't use the `getFragments()` method. It is marked with `@hide` and was not supposed to be included with the support library jar. It should not be considered as a part of the exported API. – James Wald Mar 25 '14 at 06:41
  • Heh, then they should have created a method that lets you do exactly what `getFragments()` does, because you need it quite often. I think it's actually publicly available now, too. – EpicPandaForce Jun 27 '19 at 13:08
10

This is the simplest solution and work for me.

1.) you add your fragment

ft.replace(R.id.container_layout, fragment_name, "fragment_tag").commit();

2.)

FragmentManager fragmentManager = getSupportFragmentManager();

Fragment currentFragment = fragmentManager.findFragmentById(R.id.container_layout);

if(currentFragment.getTag().equals("fragment_tag"))

{

 //Do something

}

else

{

//Do something

}
RGA
  • 2,577
  • 20
  • 38
Gau
  • 141
  • 2
  • 7
9

It might be late but I hope it helps someone else, also @CommonsWare has posted the correct answer.

FragmentManager fm = getSupportFragmentManager();
Fragment fragment_byID = fm.findFragmentById(R.id.fragment_id);
//OR
Fragment fragment_byTag = fm.findFragmentByTag("fragment_tag");
Ahmad Ali Nasir
  • 1,382
  • 3
  • 16
  • 29
  • 9
    This doesn't allow you to get the active fragment, since you don't necessarily know the id or tag. – Justin Feb 26 '14 at 17:26
7

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

madx
  • 6,723
  • 4
  • 55
  • 59
6

You can create field in your parent Activity Class:

public class MainActivity extends AppCompatActivity {

    public Fragment fr;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

}

And then inside each fragment class:

public class SomeFragment extends Fragment {

@Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        ((MainActivity) getActivity()).fr = this;
}

Your 'fr' field is current fragment Object

It's working also with popBackStack()

buxik
  • 2,583
  • 24
  • 31
4

I know it's been a while, but I'll this here in case it helps someone out.

The right answer by far is (and the selected one) the one from CommonsWare. I was having the same problem as posted, the following

MyFragmentClass fragmentList = 
            (MyFragmentClass) getSupportFragmentManager().findFragmentById(R.id.fragementID);

kept on returning null. My mistake was really silly, in my xml file:

<fragment
    android:tag="@+id/fragementID"
    android:name="com.sf.lidgit_android.content.MyFragmentClass"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

The mistake was that I had android:tag INSTEAD OF android:id.

Chayemor
  • 3,577
  • 4
  • 31
  • 54
3
  1. Do a check (which fragment in the activity container) in the onStart method;

    @Override
    protected void onStart() {
    super.onStart();
    Fragment fragmentCurrent = getSupportFragmentManager.findFragmentById(R.id.constraintLayout___activity_main___container);
    }
    
  2. Some check:

    if (fragmentCurrent instanceof MenuFragment) 
    
2

@Hammer response worked for me, im using to control a floating action button

final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View view) {
            android.app.Fragment currentFragment = getFragmentManager().findFragmentById(R.id.content_frame);
            Log.d("VIE",String.valueOf(currentFragment));
            if (currentFragment instanceof PerfilFragment) {
                PerfilEdit(view, fab);
            }
        }
});
2

If you are extending from AbstractActivity, you could use the getFragments() method:

for (Fragment f : getFragments()) {
    if (f instanceof YourClass) {
        // do stuff here
    }
}
1

If you are defining the fragment in the activity's XML layour then in the Activity make sure you call setContentView() before calling findFragmentById().

Anders R. Bystrup
  • 15,729
  • 10
  • 59
  • 55
IvancityM
  • 11
  • 2
1

If you are using the BackStack...and ONLY if you are using the back stack, then try this:

rivate Fragment returnToPreviousFragment() {

    FragmentManager fm = getSupportFragmentManager();

    Fragment topFrag = null;

    int idx = fm.getBackStackEntryCount();
    if (idx > 1) {
        BackStackEntry entry = fm.getBackStackEntryAt(idx - 2);
        topFrag = fm.findFragmentByTag(entry.getName());
    }

    fm.popBackStack();

    return topFrag;
}
James Barwick
  • 438
  • 3
  • 8
1

This will give you the current fragment class name -->

String fr_name = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
Biplob Das
  • 2,818
  • 21
  • 13
1

I recently worked on an activity involving multiple fragments so thought to share the method I used here:

Firstly, I declared a function getCurrentFragment() which returned me, yeah you guessed it, the current fragment, lol.

private fun getCurrentFragment(): Fragment? {
    return supportFragmentManager.findFragmentById(R.id.fragmentContainerView)
}

Then I override the onBackPressed function in the activity to define the navigation within fragments. Suppose, I wanted to show fragment 2 if user is in fragment 3 and presses back so I did something like this to achieve this

override fun onBackPressed() {
        if (getCurrentFragment() is Fragment3) {
            showFragment2()
        } else {
            super.onBackPressed()
        }
    }

And in showFragment2() I did something like this:

private fun showFragment2() {
        val fragment = Fragment2.newInstance()
        supportFragmentManager.commit {
            replace(R.id.FragmentContainerView, fragment, "Add a tag here")
        }
    }

I think this should give better idea to people looking on how to navigate through fragments within an activity.

shivang
  • 266
  • 3
  • 7
0

you can check which fragment is currently loaded by this

        supportFragmentManager.addOnBackStackChangedListener {
        val myFragment = supportFragmentManager.fragments.last()

        if (null != myFragment && myFragment is HomeFragment) {
            //HomeFragment is visible or currently loaded
        } else {
            //your code
        }
    }
Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
0

I use the following function in Kotlin:

supportFragmentManager.fragments.run {
    getOrNull(size - 1)?.let { currentFragment ->
        ...
    }
}
Andre Thiele
  • 3,202
  • 3
  • 20
  • 43