I am building this Android Application and I have this Activity where I have a ViewPager that hosts 4 different Fragments. The user can swipe among those fragments and see their data. I also have a menu where the user can delete or send records displayed on the 4 Fragments.
In order to figure out which fragment is active, I run this code (from the Activity where the viewPager is):
int activeItem = viewPager.getCurrentItem();
Log.e(TAG, "activeItem = " + activeItem);
Fragment fragment = this.getSupportFragmentManager().getFragments().get(activeItem);
String fragmentName = fragment.getClass().getSimpleName();
Log.e(TAG, "fragment name = " + fragmentName);
if(activeItem == 0) {
showDialog("Confirm Send", "Would you like to send the checked items?",
actionSend, RecordsSent, fragment);
}
else{
showDialog("Confirm Send", "Would you like to send the checked items?",
actionSend, RecordsPending, fragment);
}
What I do is I get the active item, then get the fragment at that index (using getSupportFragmentManager()
). And then based on what the active item is, I have a good idea which Fragment is active.
This was working for quite some time until I added another fragment and all of a sudden, I was getting a ClassCastException
. Because in my showDialog
function, I do something like:
RecordsSent rsFragment = (RecordsSent) fragment;
And what was happening is that it was sending the wrong fragment! My fragments are:
RecordsSent RecordsPending RecordsSales RecordsNews
I was getting a Class Cast error because I was casting RecordsPending to RecordsSent and vice versa. I then listed my fragments with:
Log.e(TAG, "fragments = " + this.getSupportFragmentManager().getFragments().toString());
And then it showed RecordsPending first then RecordsSent. No wonder I was getting a ClassCastException. getCurrentItem was returning 0, and item 0 in the supportFragmentManager
is RecordsPending instead of RecordsSent.
I don't know what prompted the switch between the indices of my Fragments, which makes this conundrum all the more puzzling.
Here's the code I used to initialize the Fragments.
TextView tv1 = createTab("Sent", new ColorDrawable(Color.parseColor("#006633")));
TextView tv2 = createTab("Pending", new ColorDrawable(Color.parseColor("#CCCC00")));
TextView tv3 = createTab("Daily Sales Report", new ColorDrawable(Color.parseColor("#F7C05F")));
TextView tv4 = createTab("News Records", new ColorDrawable(Color.parseColor("#B72153")));
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setCustomView(tv1).setTag("Sent"));
tabLayout.addTab(tabLayout.newTab().setCustomView(tv2).setTag("Pending"));
tabLayout.addTab(tabLayout.newTab().setCustomView(tv3).setTag("Sales"));
tabLayout.addTab(tabLayout.newTab().setCustomView(tv4).setTag("News"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
//more code here
viewPager = (ViewPager) findViewById(R.id.pager);
adapter = new PagerAdapter (getSupportFragmentManager(), tabLayout.getTabCount());
Log.e(TAG, "tab count = " + tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
My PagerAdapter class looks like this:
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
RecordsSent tab1 = new RecordsSent();
return tab1;
case 1:
RecordsPending tab2 = new RecordsPending();
return tab2;
case 2:
RecordsSales tab3 = new RecordsSales();
return tab3;
case 3:
RecordsNews tab4 = new RecordsNews();
return tab4;
default:
return null;
}
}
@Override
public int getCount() {
return mNumOfTabs;
}
}
As you can see, the first item is RecordsSent, then RecordsPending. I do not know why the supportFragmentManager returns the reverse order.
I tried:
android.support.v4.app.Fragment fragment = getVisibleFragment();
String fragmentName = fragment.getClass().getSimpleName();
but it still returns the wrong fragment type.
I also tried to do this inside my if-else blocks:
if(activeItem == 0) {
Log.e(TAG, "fragment is records sent");
fragment = fm.findFragmentByTag("Sent");
showDialog(title, message,
actionDelete, RecordsSent, fragment);
}
else{
//I use "Pending" here
}
However, I get a null pointer exception when I force it.
This problem is really frustrating because it was working days ago and then suddenly it isn't.