Get Fragment by Tag

12,912

Solution 1

In findFragmentByPosition, you are not using the index, when looking for the fragment:

getSupportFragmentManager().findFragmentByTag("android:switcher:" + pagerid + ":" + pagerAdapterid + "");

The second one should be the index, not the pagerAdapterId. So the correct code would be:

getSupportFragmentManager().findFragmentByTag("android:switcher:" + pagerid + ":" + position);

There's also no need to concatenate the last empty string.

Solution 2

I used this approach in the past and it worked quite well.

In your adapter you can declare a instance variable as follow:

private Map<Integer, Fragment> mPageReferenceMap = new HashMap<Integer, Fragment>();

In your getItem() put a reference of the fragment in the map

mPageReferenceMap.put(position, f);

Override the InstantiateItem method:

/**
 * After an orientation change, the fragments are saved in the adapter, and
 * I don't want to double save them: I will retrieve them and put them in my
 * list again here.
 */
@Override
public Object instantiateItem(ViewGroup container, int position) {
   Fragment fragment = (Fragment) super.instantiateItem(container, position);
   mPageReferenceMap.put(position, fragment);
   return fragment;
}

Override the onDestroyItem to clean up references:

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    mPageReferenceMap.remove(position);
}

And finally get the fragment depending on its position:

public Fragment getFragment(int key) {
    return mPageReferenceMap.get(key);
}

Hope it helps.

Solution 3

It seems like the thing that caused my reference to go to null is because Loading fragments is done in background and when I reference those fragments the loading is not yet complete (Thank you Daniel Zolnai for poiting that out, I would give you right answer tick if u put it as a answer) My thoughts for solution is now:

-Load all the pages you have if the number of pages are small using (ViewPager).setOffScreenLimit(int limit)

-Pause the main activity and wait till all pages are loaded then continue on.

Now I am stuck at the second part, if anyone know how to wait or delay the MainActivty for loading pages to complete or force the loading task to foreground, it would be a big help to me, thanks

Share:
12,912
Thomas Dang
Author by

Thomas Dang

Updated on June 04, 2022

Comments

  • Thomas Dang
    Thomas Dang almost 2 years

    I am using a FragmentPagerAdapter to create a multi-pages UI with different fragments. What I want to do is to find the Fragment using the position of the Fragment.

    I have applied the method of finding the nametag of fragments and use .FindFragmentbyTag() but the .FindFragmentbyTag always return me null value. The structure seems to be correct so I am not sure why I get null values, please look through and help is appreciated.

    Here is the code

    MainActivity.java
    public void onCreate(Bundle savedInstanceState) {
        this.getSupportFragmentManager();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        MainActivity.instance=this;
        //Initialize pager
        vpPager = (ViewPager)findViewById(R.id.mypager);
        pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
        vpPager.setAdapter(pagerAdapter);
        this.mapFragment = (MapFragment)this.findFragmentByPosition(0);
        this.drFragment = (DRFragment)this.findFragmentByPosition(1);
        this.sensorFragment = (SensorFragment)this.findFragmentByPosition(2);
        ......
    }
    
    protected Fragment  findFragmentByPosition(int position) {
        int pagerid = this.vpPager.getId();
        long pagerAdapterid = this.pagerAdapter.getItemId(position);
        return getSupportFragmentManager().findFragmentByTag("android:switcher:" + pagerid + ":" + pagerAdapterid + "");
    }
    

    MyPagerAdapter.java
    import android.os.Parcelable;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.view.View;
    
    public class MyPagerAdapter extends FragmentPagerAdapter {
        private static final String TAG = "TM_PageAdapter";
        private static int numItems = 3;
    
        public MyPagerAdapter(FragmentManager fragmentManager){
            super(fragmentManager);
        }
    
        public int getCount() {
            return numItems;
        }
    
        @Override
        public Fragment getItem(int position) {
            switch(position){
                case 0:
                    return MapFragment.newInstance(0, "Map Information");
                case 1:
                    return DRFragment.newInstance(1, "DR Information");
                case 2: 
                    return SensorFragment.newInstance(2, "Sensor Information");
                default: 
                    return null;
            }
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            switch(position){
                case 0:
                    return "Map Information";
                case 1:
                    return "DR Information";
                case 2: 
                    return "Sensor Information";
                default:
                    return null;
            }
        }
    
        public static String makeFragmentName(int viewId, int index) {
            return "android:switcher:" + viewId + ":" + index;
       }
    
    
        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == ((View) arg1);
    
        }
    
        @Override
        public Parcelable saveState() {
            return null;
        }
    

    Here is one of the code of the .newInstance:

    public static MapFragment newInstance(int position, String title){
        MapFragment mapFragment = new MapFragment();
        Bundle args = new Bundle();
        args.putInt("current_page", 0);
        args.putString("page_tile", "Map Information");
        mapFragment.setArguments(args);
        return mapFragment;
    }
    
  • Thomas Dang
    Thomas Dang almost 10 years
    Thanks, I will try that out. Appreciate the help, will mark correct answer if it works out :)
  • Thomas Dang
    Thomas Dang almost 10 years
    The function: long pagerAdapterid = this.pagerAdapter.getItemId(position); would give out the exact same thing as position (I used debug mode and find out) so it is not problem. I also double check by change the code according to your answer. still null pointer @@. But thanks for the help
  • Daniel Zolnai
    Daniel Zolnai almost 10 years
    You are just adding an extra step then :) It is also possible, that you fragment just doesn't exist, because it is not visible, and has been destroyed. You can increase the amount of fragments being stored with ViewPager.setOffscreenPageLimit(int pages);
  • Thomas Dang
    Thomas Dang almost 10 years
    I am not sure how the fragment are created though, when I try to put a BreakPoint at the getItem(position) in the MyPagerAdapter it did not go through after the vpPager.setAdapter(pagerAdapter); The tutorial I followed is: github.com/thecodepath/android_guides/wiki/… And it seems that I have done what is needed @@.
  • Daniel Zolnai
    Daniel Zolnai almost 10 years
    It is also possible, that the ViewPager has not created the fragments yet, because you are referencing them as soon as you set the adapter. SensorFragment will surely be null, because the pager loads the first fragment, and one extra in the background.
  • Thomas Dang
    Thomas Dang almost 10 years
    Will the Pager load all of the fragments I have, since I am referencing all of the fragments. And is there a way for the main activity to wait for the loading pages to complete then continue on? Thanks for your help :)
  • Daniel Zolnai
    Daniel Zolnai almost 10 years
    You are not referencing them, you are trying to get a reference to them. You could use a ViewPager.OnPageChangeListener and ask for the reference in onPageSelected(int position).
  • Thomas Dang
    Thomas Dang almost 10 years
    My program only have 3 tabs and I intends to load them all in one go with vpPager.setOffScreenLimit(2); And since I loads all of the fragments I want to get a reference to all of them. Get onPageSelected will only give me the reference for the active page. This may seem stupid but is there a way to holds front to holds till you load all the pages in?