18

In my application, I use an Activity which holds one Fragment with FragmentTabHost and hence all its tabs are nested Fragments.

Inside an Activity which holds a Fragment with its nested Fragment, we may get a reference to attached one using onAttachedFragment().

But how to get a reference to nested Fragment from FragmentTabHost?

Blo
  • 11,903
  • 5
  • 45
  • 99
Alex Bonel
  • 1,344
  • 1
  • 9
  • 22

4 Answers4

26

Well, exploring the source code of FragmentTabHost I've found that when it adds a fragment tab, it assignes a tag of TabSpec to nested Fragment.

So to get the reference to this Fragment we should call

getChildFragmentManager().findFragmentByTag(tabSpecTag)

Alex Bonel
  • 1,344
  • 1
  • 9
  • 22
  • 1
    can you please post the code where exactly do you do the mapping because i always get NullPointerException on my reference – Ravi Nov 09 '13 at 13:13
  • 1
    @Ravi , I added this code in my fragment onActivityCreated() method there I get reference to this fragment – DavyJonesUA Jul 21 '14 at 09:07
  • You call getChildFragmentManager() on which object ? – Cozzamara Jul 03 '15 at 08:41
  • I call it in parent ```Fragment```. – Alex Bonel Jul 03 '15 at 08:52
  • If I call this `fragmentTabHost.addTab(fragmentTabHost.newTabSpec(TAG) .setIndicator(view), MyFragment.class, null);` then right after do `getSupportFragmentManager().findFragmentByTag(TAG);` I get null. I'm doing this in the Activity since I need a reference to the fragment there. Not sure how to get it to work. – ono Sep 24 '15 at 19:06
  • 1
    @ono Seems like you invoke improper fragmentManager try ```getChildFragmentManager()``` instead of ```getSupportFragmentManager()``` – Alex Bonel Sep 29 '15 at 08:29
7

I was trying this for a while, but I was getting null returned from the FragmentManager because I was trying to access the manager in onCreateView() immediately after adding.

Here is a good explanation on what happened

It's also important to note that Fragment tabs that have not yet been selected don't exist yet in the FragmentManager, and so will return null as well. I got around this by calling mTabHost.setCurrentTab(index) before trying get to the Fragment with the FragmentManager. It's not very clean, but it works.

Community
  • 1
  • 1
loadedion
  • 2,217
  • 19
  • 41
  • Well, I get a reference to the nested `Fragment` in `onViewCreated()` at the beginning of parent `Fragment`'s lifecycle, checking if `savedInstanceState` bundle is null - in this case I know what `Fragment` should appear by default and use the specific tag, in other case I get an `int` value from this bundle which represents checked tab which I saved there before and use it to make casting to specific fragment class. Also I assign nested tab reference with `OnTabChangeListener` using `TabSpec`'s tag passed to `onTabChanged()` method. – Alex Bonel Apr 11 '13 at 05:35
1

Above solutions are also working but I have one more easy solution,

 @Override
public void onTabChanged(final String tabId) {

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {

            mFragment = getChildFragmentManager().findFragmentByTag("Tagname");
        }
    },1000);
}

Here you have to implement FragmentTabHost.onTabChangeListener We have kept a second delay in fetching fragment from the childFragmentManager.

Note : You need to cast mFragment which fragment you have used.

Nirav Shah
  • 2,064
  • 5
  • 24
  • 34
  • 1
    One thing, I see as a drawback at least, is that here you make a potential memory leak, allocating memory for anonymous ```Handler``` object. After being invoked it keeps the reference to the outer class about a second. So if you quit your activity just after changing a tab you will still have a dangling reference to it in memory. You should think twice if you invoke this code inside ```Activity``` class. Moreover, if user decides to piddle with your tabs and would swipe them randomly then you swamp your message queue with ```Runnable```s and there is no way to remove them from ```Handler``` – Alex Bonel Nov 20 '14 at 05:27
  • Agree with you but I would like to get the proper location from where to call this method mFragment = getChildFragmentManager().findFragmentByTag("Tagname"); ...This is the code where I found solution. Thanks for your deep review :) – Nirav Shah Nov 21 '14 at 12:16
1

I found a solution that I like a little better because it doesn't involving executing code with a delay (which is always iffy given android hardware fragmentation and different processor speeds).

In your onTabChanged() method, before you try to find the fragment, call executePendingTransactions() on the fragment manager associated with your tabHost. It seems there are some places in the FragmentTabHost source code where they should be calling executePendingTransactions() but fail to do so.

This works every time the tab changes with one exception... the first tab that is selected still comes back null... In my specific case, I was able to handle this exception differently anyway, by putting some code in onResume.

Hope this helps.

Justin
  • 6,564
  • 6
  • 37
  • 34