13

I am learning fragments and below given is my first fragment program. A simple project where I have 2 screens. When I click the next button of first screen, second button needs to be shown.

enter image description here

I am targeting Android 2.1 and above and using compatibility package

AppMainFragmentActivity.java

public class AppMainFragmentActivity extends FragmentActivity {
  @Override
  protected void onCreate(Bundle arg0) {
    super.onCreate(arg0);
    setContentView(R.layout.app_main_layout);
  }
}

app_main_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent" android:layout_height="fill_parent"
  android:orientation="vertical" android:id="@+id/fragment_container">

   <fragment class="com.research.fragmentstudy.FirstFragment"     
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" 
      android:id="@+id/id_first_fragment"/>

</LinearLayout>

FirstFragment.java

public class FirstFragment extends Fragment {
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.first_fragment_layout
                 , container,false);

     Button nextButton =(Button) view.findViewById(R.id.button);
     nextButton.setOnClickListener(nextListener);
     return view;
  }

  private OnClickListener nextListener  =   new OnClickListener() {
     @Override
     public void onClick(View v) {
        FragmentManager fm = ((AppMainFragmentActivity)FirstFragment.this
                           .getActivity()).getSupportFragmentManager();
        SecondFragment fragment = new SecondFragment();
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(R.id.fragment_container, fragment);
        ft.commit();
     }
  };
}

first_fragment_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:orientation="vertical" android:id="@+id/first_fragment_root">

   <TextView android:layout_height="wrap_content" 
       android:layout_width="fill_parent"
       android:text="Fragment 1" android:gravity="center_horizontal" />

   <Button android:layout_height="wrap_content" 
       android:layout_gravity="center_horizontal"
       android:layout_width="wrap_content" android:id="@+id/button"
       android:text="Next" />

</LinearLayout>

SecondFragment.java

public class SecondFragment extends Fragment {
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
      View view = inflater.inflate(R.layout.second_fragment_layout,
                     container,false);
      return view;
   }
}

second_fragment_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:orientation="vertical" android:id="@+id/first_fragment_root">

   <TextView android:layout_height="wrap_content" 
      android:layout_width="fill_parent"
      android:text="Fragment 2" android:gravity="center_horizontal" />

</LinearLayout>

Well I am getting the first screen alright. Now,

What I expected, from my understanding of fragment

  • When I click the Next button in screen 1, SecondFragment is created, its onCreate() and onCreateView() gets called.
  • SecondFragment is shown, and FirstFragment gets destroyed (since I am not adding it to backstack). There won't be any animation since default fragment transaction doesn't have animation.

What is happening

  • SecondFragment is getting created alright, its onCreate() and onCreateView() gets called.
  • But FirstFragment remains on the screen, and second one never showing.

Now my understanding of fragment can be wrong. But I believe when we commit() a fragment transaction, first fragment should be replaced by second one (first one either gets hidden or destroyed). Well nothing seems to be happening. Why is that? Should we manually destroy/hide first fragment?

Note : I know it is a long question for such a basic thing. But I put my entire code since I am not sure where I messed it up.

Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167

3 Answers3

17

Well I got it working. Both answers given to this questions correctly tells one reason for my code to not work as expected. But there were 2 errors in my code.

using fragmentTransaction.add() won't show new fragment over old one. you need to call replace(). The answers given were right.

But there was one more error in my code. You can't replace a fragment created statically in xml. So I changed

app_main_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent" android:layout_height="fill_parent"
  android:orientation="vertical" android:id="@+id/fragment_container">

</LinearLayout>

and

AppMainFragmentActivity.java

public class AppMainFragmentActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);
        setContentView(R.layout.app_main_layout);

        FragmentManager fragmentManager = getSupportFragmentManager();
        FirstFragment fragment = new FirstFragment();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container,fragment);
        fragmentTransaction.commit();           
    }
}
Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167
  • This is a trap! For there are so many functions called add()...but only fragmentTransaction.add(R.id.fragment_container,fragment); work...waste of time... – Robert Mar 26 '13 at 10:46
  • @Krishnabhadra I mean before I saw your solution, it took almost an hour to check what's wrong...really waste time. In my case, I'm adding fragment to an empty activity without setContentView(). It also display nothing but empty black area. Really THANK YOU for pointing out this! – Robert Mar 26 '13 at 15:26
  • Remark: When adding, you need to check if the fragment has been created before. – stdout May 24 '16 at 21:35
8

Have you tried using ft.replace(R.id.fragment_container, fragment) instead of add ? add will not remove the existing fragment.

  • 1
    Even if add doesn't remove the existing fragment, should secondfragment be visible on screen over first one? If not what is the use of this fragment transaction? Regarding your answer,when I use replace instead of add, second fragment is not showing. – Krishnabhadra Sep 14 '12 at 04:59
  • So we need to remove, create fragment just like we add and remove to a layout. So what is the use of this FragmentTransaction? – Krishnabhadra Sep 14 '12 at 05:11
  • Since there is no default stacking of fragment, when a fragment goes offscreen, it is destoyed right then. So when I go to fragment A to B and to go back to A I need to create A from scratch right? – Krishnabhadra Sep 14 '12 at 05:15
  • Regarding your first question, FragmentTransaction are used to add / remove / replace fragments in a particular layout at runtime. There is no default stacking, but you can add a particular fragment transaction to the back stack by calling addToBackStack(string) & the popping the stack using Fragment manager – Sujai Kamat Sep 14 '12 at 05:32
2

You are trying to add one more fragment in fragment_container, It is adding but your fragment wont visible because you have specified width and height for id_first_fragment as fill_parent so try to set wrap_content for id_first_fragment fragment . you can see the next fragment when you click on button . If you want to close first fragment and show second one you need to replace instead of add .

Nagarajan
  • 238
  • 1
  • 7