I have successfully set up tabs in the Action Bar using the following example from Google themselves at http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html as a bases. My code looks like so:
public class Main extends SherlockFragmentActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = getSupportActionBar().newTab();
tab1.setIcon(R.drawable.ic_tab_example_selected);
tab1.setTabListener(new TabListener<Tab1>(this, "A", Tab1.class));
getSupportActionBar().addTab(tab1);
ActionBar.Tab tab2 = getSupportActionBar().newTab();
tab2.setIcon(R.drawable.ic_tab_example_selected);
tab2.setTabListener(new TabListener<Tab2>(this, "B", Tab2.class));
getSupportActionBar().addTab(tab2);
ActionBar.Tab tab3 = getSupportActionBar().newTab();
tab3.setIcon(R.drawable.ic_tab_example_selected);
tab3.setTabListener(new TabListener<Tab3>(this, "C", Tab3.class));
getSupportActionBar().addTab(tab3);
ActionBar.Tab tab4 = getSupportActionBar().newTab();
tab4.setIcon(R.drawable.ic_tab_example_selected);
tab4.setTabListener(new TabListener<Tab4>(this, "D", Tab4.class));
getSupportActionBar().addTab(tab4);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
public class TabListener<T extends Fragment> implements ActionBar.TabListener {
private Fragment mFragment;
private final SherlockFragmentActivity mActivity;
private final String mTag;
private final Class<T> mClass;
/** Constructor used each time a new tab is created.
* @param activity The host Activity, used to instantiate the fragment
* @param tag The identifier tag for the fragment
* @param clz The fragment's Class, used to instantiate the fragment
*/
public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(mFragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
}
With this I have multiple tabs that switch between the different fragments in each tab. However, my problem starts when in a tab and changing fragments from within a tab. This is the problem:
When I am in Tab 1, I swap the initial fragment loaded in the tab with a new fragment. I then go to Tab 2 which shows it's initial fragment. However, the view of the fragment swapped to in Tab 1 still shows behind Tab 2 fragment:
This is code I am currently using to change the fragment from within Tab 1:
// Create new fragment and transaction
FragmentTransaction transaction = ctx.getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(container, fragment, tag);
if(addToBackStack)
transaction.addToBackStack(tag);
// Commit the transaction
transaction.commit();
All this is being accomplished via ActionBar Sherlock and Google v4 support library.
Ok, so this answer assumes you want to wipe each tabs back history every time you swap tabs. What I mean by that is Tab 1 starts on frag 1, then you click and change it to frag 2. If you select Tab 2, you will be undoing the history of Tab 1 and next time you click Tab 1 you will be back to frag 1.
With that said here is the solution: Replace your onTabUnselected with the below
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
//this segment removes the back history of everything in the tab you are leaving so when you click on the tab again you go back to a fresh start
FragmentManager man = mActivity.getFragmentManager();
if(man.getBackStackEntryCount()>0) //this check is required to prevent null point exceptions when clicking off of a tab with no history
man.popBackStack(man.getBackStackEntryAt(0).getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); //this pops the stack back to index 0 so you can then detach and then later attach your initial fragment
//also it should be noted that if you do popbackstackimmediate here instead of just popbackstack you will see a flash as the gui changes back to the first fragment when the code executes
//end
ft.detach(mFragment);
}
}