Hopeless Hopeless - 3 months ago 60
Android Question

Why could FragmentManager.FindFragmentById be used against FrameLayout?

I totally don't understand a piece of code in the Xamarin example about using Tab at here https://developer.xamarin.com/samples/HelloTabsICS

As I understand

should return a
and the id should be of course some
defined in XML files under
folder. But the code from the link above has something strange to me, here is one layout xml file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_weight="1" />

And the following code (in the example demo) can find out a
from the id
which is of a
? That totally does not make any sense to me, here is the code:

var fragment = this.FragmentManager.FindFragmentById(Resource.Id.fragmentContainer);
if (fragment != null)

Why can the id of
be used to find out an instance of
? It's really confusing at that point.

I'm fairly new to Xamarin.Android as well as Android programming (just experienced for 5 days). So please help me explain that strange thing.

Thank you very much!


This is because that FrameLayout is containing a Fragment, that you can implement programmatically.

Let's assume you have a fragment, like FirstFrag.cs, containing no matter what UI elements doing no matter what code. You can instantiate this fragment inside your FrameLayout doing this :

FragmentTransaction tx = FragmentManager.BeginTransaction ();
tx.Replace (Resource.Id.fragmentContainer, new FirstFrag ());
tx.Commit(); //Where fragmentContainer is your FrameLayout.
//Also note that tx.Replace is acting like tx.Add if there is no fragment.

Then, using FindFragmentById on that FrameLayout, you will be able to get the FirstFrag contained in it as a Fragment object. Better, you can directly get it as a FirstFrag :

FirstFrag frag = FragmentManager.FindFragmentById<FirstFrag>(Resource.id.fragmentContainer);

The FrameLayout is simply acting as a container for your fragments. You can use any layout, depending on how you wish to display the fragment content.

Now let's assume you have a second fragment, called SecondFrag.cs. If you add it to your container using tx.Add(), it will stack with the first one into the container. If you use Replace instead, you will erase the first one. But it seems like a bad idea to have two fragments in the same container. Ideally, you want to have a single fragment per container.

If you really need to put two fragments inside a container, you can add a Tag to the fragment doing this :

FragmentTransaction tx = FragmentManager.BeginTransaction();
tx.Add(Resource.id.fragmentContainer, new SecondTag(), "YourTag");

Then, to find a precise fragment from your container, you can do this :

var frag = FragmentManager.FindFragmentByTag("YourTag");

But again, it's not a good idea. One fragment per container is the way to go.

NOTE : I had weird results trying to get the fragment from the container immediately after the commit. It was always giving me the previous content of the container. I guess it's planned to work this way, but it seems like the commit is really applied once the method it was called in is over.

Hope I've been clear enough, feel free to ask for more details !