118

I am developing application which contains 2 fragments and i want to show hide according to my need. Following code has simple example of my problem. This simple Fragmentactivity contains 1 button and one listfragment.

This simple example works flawless. but i am not satisfied with show hide fragment. If you remove layout.setVisibility(View.GONE); from the code then ft.hide(f); will not hide fragment. In fact we are not hiding fragment we are hiding container.

My Question is, IS this a way to show hide fragments? If not then please explain with tested example How to hide and show Fragments because lots of people are facing this problem.

 public class MainActivity extends FragmentActivity implements OnClickListener {

        Fragment1 f;
        Button b;
        LinearLayout layout;
        Fragment myf;
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            b = (Button) findViewById(R.id.button1);
            layout = (LinearLayout) findViewById(R.id.ll);
            f = new Fragment1();
        }

        @Override
        public void onClick(View v) {

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

            if (f.isHidden()) {
                ft.show(f);
                layout.setVisibility(View.VISIBLE);
                b.setText("Hide");
            } else {
                ft.hide(f);
                b.setText("Show");
                layout.setVisibility(View.GONE);
            }
            ft.commit();
            // TODO Auto-generated method stub
        }
abidkhan303
  • 1,761
  • 3
  • 18
  • 31
  • Why do you need to set visibility of container? It should work without setting visibility. – Andrii Chernenko Jan 15 '13 at 22:03
  • Exactally it should work without visibility of container but its not working. Please please please share simple working example with me. Then i would know where i am missing. – abidkhan303 Jan 16 '13 at 08:47
  • 1
    My guess is that you are trying to show/hide different instance of fragment each time. When you add your fragment (I don't see this piece of code, by the way) add it with tag and then retrieve it by that tag (instead of trying to store reference to it). That might be what you're missing. – Andrii Chernenko Jan 16 '13 at 08:59

10 Answers10

173

Don't mess with the visibility flags of the container - FragmentTransaction.hide/show does that internally for you.

So the correct way to do this is:

FragmentManager fm = getFragmentManager();
fm.beginTransaction()
          .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
          .show(somefrag)
          .commit();

OR if you are using android.support.v4.app.Fragment

 FragmentManager fm = getSupportFragmentManager();
 fm.beginTransaction()
          .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
          .show(somefrag)
          .commit();
Alan
  • 1,510
  • 1
  • 18
  • 35
numan salati
  • 19,394
  • 9
  • 63
  • 66
  • 6
    Why do you recommend against messing with the flags directly? (I'm not disputing your recommendation, just trying to understand it.) – Ellen Spertus Feb 16 '14 at 03:52
  • 1
    Yes, I read that in your original message. I was hoping you could add justification for the extra overhead. In the meantime, I've discovered some, such as the option of adding to the back stack. – Ellen Spertus Feb 17 '14 at 23:05
  • 2
    It is error prone because you can change your flags at low level api and high level api and if you aren't careful (i.e flags get out of sync) you could be chasing weird bugs. Thats is why its recommended to use the fragment manager to hide and show your fragments. – numan salati Feb 17 '14 at 23:08
  • @numansalati Hi, is there any compatibilty (from support library) version of `android.R.animator.fade_in`, and `android.R.animator.fade_out`? – Solace Jan 20 '15 at 19:07
  • 1
    With the container, you can set it to SHOW, HIDE, or GONE. There is no GONE option when hiding a fragment. – Stealth Rabbi May 12 '15 at 15:42
  • If your Fragment extends android.support.v4.app.Fragment make sure to use getSupportFragmentManager(); – Alan Apr 26 '17 at 18:45
  • @abidkhan303 you can check this article as well: https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711 – mochadwi Jan 13 '19 at 15:01
  • I'm assuming you are not obligated to provide custom animations. – danmaze Mar 28 '20 at 19:31
60

In addittion, you can do in a Fragment (for example when getting server data failed):

 getView().setVisibility(View.GONE);
Arià
  • 894
  • 2
  • 10
  • 16
25

Hi you do it by using this approach, all fragments will remain in the container once added initially and then we are simply revealing the desired fragment and hiding the others within the container.

// Within an activity
private FragmentA fragmentA;
private FragmentB fragmentB;
private FragmentC fragmentC;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState == null) {
        fragmentA = FragmentA.newInstance("foo");
        fragmentB = FragmentB.newInstance("bar");
        fragmentC = FragmentC.newInstance("baz");
    }
}


// Replace the switch method
protected void displayFragmentA() {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    if (fragmentA.isAdded()) { // if the fragment is already in container
        ft.show(fragmentA);
    } else { // fragment needs to be added to frame container
        ft.add(R.id.flContainer, fragmentA, "A");
    }
    // Hide fragment B
    if (fragmentB.isAdded()) { ft.hide(fragmentB); }
    // Hide fragment C
    if (fragmentC.isAdded()) { ft.hide(fragmentC); }
    // Commit changes
    ft.commit();
}

Please see https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments for more info. I hope I get to help anyone. Even if it this is an old question.

mangu23
  • 884
  • 9
  • 13
  • 1
    so you have to have two more methods like displayFragmentB() and displayFragmentC()? – temirbek Jan 24 '17 at 11:30
  • yes @temirbek you can just follow how displayFragmentA() method is implemented. – mangu23 Jan 25 '17 at 22:15
  • 1
    If you have many fragments in one activity (2 or more) and that you are using the method above, please use [this](https://stackoverflow.com/a/46676381/3808178). It will be easier to write and to read. – Maxime Claude Oct 10 '17 at 21:37
11
public void showHideFragment(final Fragment fragment){

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.setCustomAnimations(android.R.animator.fade_in,
                    android.R.animator.fade_out);

    if (fragment.isHidden()) {
        ft.show(fragment);
        Log.d("hidden","Show");
    } else {
        ft.hide(fragment);
        Log.d("Shown","Hide");                        
    }

    ft.commit();
}
Jyo the Whiff
  • 829
  • 9
  • 23
10

Try this:

MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.mapview);
mapFragment.getView().setVisibility(View.GONE);
Ingo
  • 5,239
  • 1
  • 30
  • 24
5

I may be way way too late but it could help someone in the future.
This answer is a modification to mangu23 answer
I only added a for loop to avoid repetition and to easily add more fragments without boilerplate code.

We first need a list of the fragments that should be displayed

public class MainActivity extends AppCompatActivity{
    //...
    List<Fragment> fragmentList = new ArrayList<>();
}

Then we need to fill it with our fragments

@Override
protected void onCreate(Bundle savedInstanceState) {
    //...
    HomeFragment homeFragment = new HomeFragment();
    MessagesFragment messagesFragment = new MessagesFragment();
    UserFragment userFragment = new UserFragment();
    FavoriteFragment favoriteFragment = new FavoriteFragment();
    MapFragment mapFragment = new MapFragment();

    fragmentList.add(homeFragment);
    fragmentList.add(messagesFragment);
    fragmentList.add(userFragment);
    fragmentList.add(favoriteFragment);
    fragmentList.add(mapFragment);
}

And we need a way to know which fragment were selected from the list, so we need getFragmentIndex function

private int getFragmentIndex(Fragment fragment) {
    int index = -1;
    for (int i = 0; i < fragmentList.size(); i++) {
        if (fragment.hashCode() == fragmentList.get(i).hashCode()){
            return i;
        }
    }
    return index;
}

And finally, the displayFragment method will like this:

private void displayFragment(Fragment fragment) {
        int index = getFragmentIndex(fragment);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (fragment.isAdded()) { // if the fragment is already in container
            transaction.show(fragment);
        } else { // fragment needs to be added to frame container
            transaction.add(R.id.placeholder, fragment);
        }
        // hiding the other fragments
        for (int i = 0; i < fragmentList.size(); i++) {
            if (fragmentList.get(i).isAdded() && i != index) {
                transaction.hide(fragmentList.get(i));
            }
        }
        transaction.commit();
    }

In this way, we can call displayFragment(homeFragment) for example.
This will automatically show the HomeFragment and hide any other fragment in the list.
This solution allows you to append more fragments to the fragmentList without having to repeat the if statements in the old displayFragment version.
I hope someone will find this useful.

Mohamed Medhat
  • 761
  • 11
  • 16
2

From my code, comparing to above solution, the simplest way is to define a layout which contains the fragment, then you could hide or unhide the fragment by controlling the layout attribute which is align with the general way of view. No additional code needed in this case and the additional deployment attributes of the fragment could be moved to the outer layout.

<LinearLayout style="@style/StHorizontalLinearView"
    >

    <fragment
        android:layout_width="match_parent"
        android:layout_height="390dp"
        android:layout_alignParentTop="true"
        />

</LinearLayout>
BrainAtom
  • 29
  • 3
2
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

In onCreate, after setContentView, i hid two fragments and committed them to the fragment manager, but i didn't hide the first fragment that will serve as home.

fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
 @Override
    public void onClick(View v) {
        Fragment another = fragment1;
         if(active==fragment1){
          another = fragment2;
         }
            fm.beginTransaction().hide(active).show(another).commit();
            active = another;
}

Ref : https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711

Rachit Vohera
  • 707
  • 7
  • 10
0

This worked for me

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        if(tag.equalsIgnoreCase("dashboard")){

            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.show(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.hide(showcaseFragment);

        } else if(tag.equalsIgnoreCase("showcase")){
            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.hide(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.show(showcaseFragment);
        }

        ft.commit();
shankey
  • 343
  • 2
  • 9
0

the answers here are correct and i liked @Jyo the Whiff idea of a show and hide fragment implementation except the way he has it currently would hide the fragment on the first run so i added a slight change in that i added the isAdded check and show the fragment if its not already

public void showHideCardPreview(int id) {
    FragmentManager fm = getSupportFragmentManager();
    Bundle b = new Bundle();
    b.putInt(Constants.CARD, id);
    cardPreviewFragment.setArguments(b);
    FragmentTransaction ft = fm.beginTransaction()
        .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
    if (!cardPreviewFragment.isAdded()){
        ft.add(R.id.full_screen_container, cardPreviewFragment);
        ft.show(cardPreviewFragment);
    } else {
        if (cardPreviewFragment.isHidden()) {
            Log.d(TAG,"++++++++++++++++++++ show");
            ft.show(cardPreviewFragment);
        } else {
            Log.d(TAG,"++++++++++++++++++++ hide");
            ft.hide(cardPreviewFragment);
        }
    }

    ft.commit();
} 
martinseal1987
  • 1,862
  • 8
  • 44
  • 77