1

I'm making an Android app that uses the action bar tabs (I'm using the support library's action bar), each associated with a fragment that I generate dynamically.

The idea is to show the fragment whenever its tab is selected using FragmentTransaction.show() and hide the deselected tab with FragmentTransaction.hide(), but when I do this, the 'hidden' fragment simply becomes slightly greyed out.

The fact that the UI indicates that something is different by greying out the hidden tab might suggest that this is intentional behavior, but I was under the impression that hide() actually hid the tabs.

What am I doing wrong and what should I do? The code for the tab listener is below if necessary:

public class VarientTabListener implements ActionBar.TabListener
{
    VarientFragment Arch_Fragment;
    VarientFragment Plane_Fragment;
    ActionBarActivity parent;

    public VarientTabListener(ActionBarActivity act)
    {
        parent = act;
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
    {
        //Work out which tab was selected
        if (tab.getText() == "Arch_Tab")
        {
            //Create the tab if it doesn't exist
            if (Arch_Fragment == null)
            {
                Arch_Fragment = (VarientFragment) Fragment.instantiate(parent, VarientFragment.class.getName());
                ft.add(android.R.id.content, Arch_Fragment, "Arch");
            }
            //Otherwise show it
            else
            {
                ft.show(Arch_Fragment);
            }
        }
        else if (tab.getText() == "Plane_Tab")
        {
            if (Plane_Fragment == null)
            {
                Plane_Fragment = (VarientFragment) Fragment.instantiate(parent, VarientFragment.class.getName());
                ft.add(android.R.id.content, Plane_Fragment, "Plane");
            }
            else
            {
                ft.show(Plane_Fragment);
            }
        }
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
    {
        if (tab.getText() == "Arch_Tab")
        {
            if (Arch_Fragment != null)
            {
                //Hide the unselected tab
                ft.hide(Arch_Fragment);
            }

        }
        else if (tab.getText() == "Plane_Tab")
        {
            if (Plane_Fragment != null)
            {
                ft.hide(Plane_Fragment);
            }
        }
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft)
    {

    }
}
Migwell
  • 18,631
  • 21
  • 91
  • 160

3 Answers3

3

you need to commit the fragment

ft.hide(Arch_Fragment);
ft.commit();
Hardik
  • 17,179
  • 2
  • 35
  • 40
  • I'm pretty sure that ft.commit() is called automatically by the tab. I've never seen an example of a TabListener using ft.commit (e.g. [1](http://ramsandroid4all.blogspot.com.au/2013/06/android-actionbar-tab-example-1.html), [2](http://arvid-g.de/12/android-4-actionbar-with-tabs-example), [3](http://www.lucazanini.eu/2012/android/tab-layout-in-android-with-actionbar-and-fragment/)) I get `java.lang.IllegalStateException: commit already called` if I use ft.commit() – Migwell Dec 20 '13 at 12:55
  • you can check this answer==> http://stackoverflow.com/questions/8432193/how-to-implement-show-and-hide-fragment-inside-fragment-in-android – Hardik Dec 20 '13 at 13:05
2

because you are comparing Strings in a wrong way. don't comapare Strings with == operator.

use equals() method to compare Strings...

if (tab.getText().equals("Arch_Tab")) {
    if (Arch_Fragment != null) {
        //Hide the unselected tab
         ft.hide(Arch_Fragment);
    }
 }
Gopal Gopi
  • 11,101
  • 1
  • 30
  • 43
  • Hmm I'll agree this is better practise but for whatever reason these lines were actually working as intended (maybe Android overrides the == operator or maybe this worked by pure luck), so this can't be the problem. And why would the hidden fragment get greyed out if the code was never run? – Migwell Dec 20 '13 at 12:57
1

While I didn't manage to really solve this problem, a workaround is to simply get a new FragmentTransaction and commit that at the end, ignoring the transaction you get passed as an argument.

For example for the onTabUnselected method:

@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft_unused)
{
    FragmentTransaction ft = parent.getSupportFragmentManager().beginTransaction();
    if (tab.getText() == "Arch_Tab")
    {
        if (Arch_Fragment != null)
        {
            //Hide the unselected tab
            ft.hide(Arch_Fragment);
        }

    }
    else if (tab.getText() == "Plane_Tab")
    {
        if (Plane_Fragment != null)
        {
            ft.hide(Plane_Fragment);
        }
    }
    ft.commit();
}
Migwell
  • 18,631
  • 21
  • 91
  • 160