120

How can I set a Fragment's Id so that I can use getSupportFragmentManager().findFragmentById(R.id.--)?

Macarse
  • 91,829
  • 44
  • 175
  • 230
tyb
  • 4,749
  • 11
  • 31
  • 38

7 Answers7

119

You can't set a fragment's ID programmatically.

There is however, a String tag that you can set inside the FragmentTransaction which can be used to uniquely identify a Fragment.

As Aleksey pointed out, you can pass an ID to FragmentTransaction's add(int, Fragment) method. However, this does not specify the ID for a Fragment. It specifies the ID of a ViewGroup to insert the Fragment into. This is not that useful for the purpose I expect you have, because it does not uniquely identify Fragments, but ViewGroups. These IDs are of containers that one or more fragments can be added to dynamically. Using such a method to identify Fragments would require you to add ViewGroups dynamically to the Layout for every Fragment you insert. That would be pretty cumbersome.

So if your question is how to create a unique identifier for a Fragment you're adding dynamically, the answer is to use FragmentTransaction's add(int containerViewId, Fragment fragment, String tag) method and FragmentManager's findFragmentByTag(String) method.

In one of my apps, I was forced to generate strings dynamically. But it's not that expensive relative to the actual FragmentTransaction, anyway.

Another advantage to the tag method is that it can identify a Fragment that isn't being added to the UI. See FragmentTransaction's add(Fragment, String) method. Fragments need not have Views! They can also be used to persist ephemeral state between config changes!

Thomas Dignan
  • 7,052
  • 3
  • 40
  • 48
  • If I use the tag and not the ID for the fragment, how would I use the replace call which needs a fragment resource id? – Namratha Jan 22 '13 at 09:32
  • 12
    @TomDignan how about a fragment that will be added in a ViewPager? How can I set his tag? I can't use transactions in this situation. – GuilhE Jan 22 '15 at 17:16
  • 1
    @GuilhE Activity provides an addFragment() method which you can reference from the viewpager. Keeping the tag before that could be accomplished with a hashmap. – Thomas Dignan Feb 11 '15 at 04:56
  • 1
    Can the answer be edited a tiny bit to emphasize that you can set id in xml layout? Because I personally did not read other questions and was under impression that there is no way at all to set id to the fragment... – Ivan Apr 03 '17 at 13:42
45

Turns out you may not need to know the fragment id.

From the docs:

public abstract Fragment findFragmentById (int id)

Finds a fragment that was identified by the given id either
when inflated from XML or as the container ID when added in
a transaction.

The important part is "as the container ID when added in a transaction".

so:

getSupportFragmentManager()
    .beginTransaction()
    .add(R.id.fragment_holder, new AwesomeFragment())
    .commit();

and then

AwesomeFragment awesome = (AwesomeFragment)
     getSupportFragmentManager()
          .findFragmentById(R.id.fragment_holder);

will get you whatever (awesome) fragment is held in R.id.fragment_holder.

Moose Morals
  • 1,628
  • 25
  • 32
4

In most cases you can use the fragment tag as well as the ID.
You can set the tag value in FragmentTransaction.add(Fragment fragment, String tag );. Then you can use the command FragmentManager.findFragmentByTag(String tab) to find the fragment in question.

jenzz
  • 7,239
  • 6
  • 49
  • 69
2

As Tom and others already mention, there are ways to put a tag on a fragment and use that tag for identification. A subsequent problem I've come across with those solutions is that the fragment doesn't get a tag until it's associated with the Activity (or, actually, the FragmentManager). What to do if one needs to identify a fragment before it has been tagged?

My solutions so far all rely on the oldest (Java) trick in the world: create a minimalistic template fragment which takes an id in one of it's constructors and provides a getFragmentId() method which returns that id. I then let those fragments that need early identification extend that template and; voila! Problem solved.

This solution might, unfortunately, require a set of template fragments, one for each fragment type, ListFragment, DialogFragment or plain old Fragment (POFO?!) that need early identification. But this is manageable in the case of fragments I think, considering the gains provided.

Sorry for tearing up healing wounds :-)

Cheers!

dbm
  • 10,376
  • 6
  • 44
  • 56
0

Use the following:

To add a fragment:

getFragmentManager().beginTransaction().add(R.id.fragment_container, fragmentToBeAdded, tag).commit();

To identify existing fragment:

getFragmentManager().findFragmentByTag(fragmentName);
Jaydev
  • 1,794
  • 20
  • 37
0

When using a tag please do make sure to add the

fragmentTransaction.addToBackStack(null); 

method so that your Fragment is resumed instead of destroyed as mentioned in the developer guides.

If you don't call addToBackStack() when you perform a transaction that removes a fragment, then that fragment is destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you do call addToBackStack() when removing a fragment, then the fragment is stopped and is later resumed if the user navigates back.

You can find this at the end of this page.

I lost about 30 minutes trying to figure out why my Fragment was not being found through a simple findFragmentByTag(); call

Panos Gr
  • 667
  • 5
  • 13
-2

In addition to Tom's answer, replace method also supports the fragment tag, in addition to add method.

oren zvi
  • 114
  • 1
  • 4