Replace one fragment with an another fragment

17,298

Solution 1

I Have worked on fragments before and hope this would help you out and give you a better understanding of the flow. Firstly, your MainActivity.xml file will look like this :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:layout_behavior="@string/appbar_scrolling_view_behavior"
   tools:context="com.example.activity.HomeActivity">


    //This frameLayout will contain all your fragments view.
   <FrameLayout
      android:id="@+id/container_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    </FrameLayout>

 </RelativeLayout>

Next, you create two fragments and their XML is mentioned below : fragment1.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true" // important to have this
    tools:context=".fragments.frament1">

     <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"/>

 </RelativeLayout>

The next fragment would look exactly the same as mentioned above. Here is the Fragment1.class:

public class Fragment1 extends Fragment implements View.OnClickListener {
Button btn;

   public Fragment1() {
    // Required empty public constructor
}

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, container, false);
        view.setBackgroundColor(Color.WHITE);

       //Perform required conditions and return view 
       button = (Button) view.findViewById(R.id.btn);
       button.setOnClickListener(this);

       return view;
      }

        public void onClick(View v) {

             switch(v.getId())
             {
                case R.id.btn: 
                 //replace current fragment on button click

                 Fragment fragment2= new Fragment2();

                 getFragmentManager().beginTransaction().
                 replace(R.id.container_view, fragment2).
                 addToBackStack("frags").commit();

               break;
             }
        }
 }

And the Fragment2 would be as follows :

 public class Fragment2 extends Fragment{
 String TAG = "Fragment2";


     public Fragment2() {
      // Required empty public constructor
   }

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

          View view = inflater.inflate(R.layout.fragment2,container,false);
          view.setBackgroundColor(Color.WHITE);
       return view;
    }
}

As I mentioned earlier, the xml file would be the same as fragment1.xml. What is more important here is that the main activity will contain a layout which will take the fragments view when ever the user switches fragments. Hence we use the replace method which would just replace the previous view with the fragments view specified by us.

Solution 2

In your Activity's onCreate function, you should be calling setContentView(R.layout.main), then when you want to load a Fragment, you choose a ViewParent within R.layout.main. The fragment will become the child of that ViewParent. So the id passed into FragmentTransaction.replace, is the id of the ViewParent in R.layout.main.

It makes sense that the Button in your allmoods RelativeLayout would remain because the FragmentTransaction.replace function only replaces an existing fragment that is in that container. Everything in R.layout.main will remain. This is how an Activity keeps static content, like drawers or toolbars.

When you load your "new fragment" you will use the same id. So the "new fragment" replaces the "old fragment" as the new child of the ViewParent within R.layout.main.

Here is the Fragments API guide.

Update:

When you call FragmentTransaction.replace in your Activity's onCreate function, this could be recreating an existing Fragment. Make sure the savedInstanceState (the Bundle passed into onCreate) is null. If the savedInstanceState is not null, then the fragment probably already exists and you can find it like this;

Fragment f = getFragmentManager().findFragmentByTag(YOUR_FRAGMENT_TAG);

Update 2:

Here is a guide that should help you. It looks like you could use FragmentPagerAdapter to simplify your fragment transactions.

Solution 3

To understand the flow of fragment transition, first of all, you have to know about its structure in activity. Let's see: a) Activity: At bottom of everything (MainActivity)

activity_main.xml :-

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

Here @+id/container is the layout over we do transitions of fragment contents.

B) FragmentA : Initially added fragment to the container of MainActivity.

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//Instance of fragment
Fragment newFragment = FragmentA.newInstance("a","b");
//It will replace the fragment content view to container of main activity
ft.replace(R.id.container, newFragment);
//FragmentA is added to back stack with it's name as a tag
ft.addToBackStack(FragmentA.class.getSimpleName());
ft.commitAllowingStateLoss();

B) FragmentB : Replace FragmentA with FragmentB

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//Instance of fragment
Fragment newFragment = FragmentB.newInstance("a","b");
//It will replace the fragment content view to container of fragment A which     // is previously replaced to main activity container
ft.replace(R.id.container, newFragment);
//FragmentB is added to back stack with it's name as a tag
ft.addToBackStack(FragmentB.class.getSimpleName());
ft.commitAllowingStateLoss();

So main thing behind this is to replace/add fragment content view to the activity container view.

Solution 4

try this once, 1. if you are passing any value upon button click In Activity

Category category=new Category();
            Bundle bundle=new Bundle();
            bundle.putString("heading",heading);
            bundle.putInt("position",position1+1);
            bundle.putString("url",url);
            bundle.putString("sku",sku);
            bundle.putBoolean("flag",flag);
            category.setArguments(bundle);

            FragmentManager fragmentManager = getSupportFragmentManager();
            final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragmentCategories,category);
            fragmentTransaction.commit();

In fragment

Bundle bundle=getArguments();
    if(getArguments()!=null) {
        position = bundle.getInt("position");
        heading = bundle.getString("heading");
        url = bundle.getString("url");
        sku=bundle.getString("sku");
        flag=bundle.getBoolean("flag");

        tvHeading.setText(heading);

        video_chapter = handler.getContent_Aspects(position);
        adapter = new Chapter_content_Adapter(getActivity(), video_chapter, url, heading, position);
        gvChapter.setAdapter(adapter);
    }

2.if simply calling fragment

FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentCategories=fragmentManager.findFragmentById(R.id.fragmentCategories);
    fragmentTransaction.commit();

Solution 5

Try the following code.

A) Create Activity as follows :

MainActivity

import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements ShowNextFragment{


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    FragmentA fragmentA=new FragmentA();
    FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.container,fragmentA);
    fragmentTransaction.addToBackStack("A");
    fragmentTransaction.commitAllowingStateLoss();

}

@Override
public void showFragment() {
    FragmentB fragmentB=new FragmentB();
    FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.container,fragmentB);
    fragmentTransaction.addToBackStack("B");
    fragmentTransaction.commitAllowingStateLoss();
}
}

B) Create 2 fragments as follows :

Fragment A

 import android.app.Fragment;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;


public class FragmentA extends Fragment {
private ShowNextFragment showNextFragment;



@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    try {

        showNextFragment=(ShowNextFragment)getActivity();
        Log.e("CAllback","Set");
    }catch (ClassCastException e){
        Log.e("Error","Please Implement ShowFragment Interface");
    }
    return inflater.inflate(R.layout.fragment_a,container,false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    view.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (showNextFragment!=null){
                showNextFragment.showFragment();
            }
        }
    });

}
}

Fragment B

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater; 
import android.view.View;
import android.view.ViewGroup;

public class FragmentB extends Fragment {



@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_b,container,false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);


}
}

C) Create an interface as follows

public interface ShowNextFragment {
void showFragment();
}

D) create following xmls as :

i) activity_main

   <?xml version="1.0" encoding="utf-8"?>
   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

  </RelativeLayout>

ii) fragment_a

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorcyan"
android:orientation="vertical">

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Show Fragment B" />
</LinearLayout>

iii) fragment_b

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorgreen"
android:orientation="vertical">

<TextView

    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Fragment B"
    android:layout_centerVertical="true"
    android:layout_alignRight="@+id/btn_camera"
    android:layout_alignEnd="@+id/btn_camera" />

<android.support.design.widget.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:backgroundTint="#ffffff"
    android:src="@android:drawable/ic_dialog_email"
    android:id="@+id/btn_camera"
    app:fabSize="mini"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true" />
 </RelativeLayout>
Share:
17,298

Related videos on Youtube

Santanu
Author by

Santanu

Programming is FUN!!

Updated on June 04, 2022

Comments

  • Santanu
    Santanu almost 2 years

    I want to replace an old Fragment with a new Fragment, but i still get the buttons of the old Fragment that is still visible in the new fragment.

    In the old one, on a button click enter image description here

    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    Fragment newFragment = GenericMood.newInstance("a","b");
    
    // Replace whatever is in the fragment_container view with this fragment,
    // and add the transaction to the back stack if needed
    transaction.replace(R.id.allmoods, newFragment);
    transaction.addToBackStack(null);
    transaction.commitAllowingStateLoss();
    

    I can replace the old Fragment with the new one, but the buttons from R.id.allmoods Fragment still visible on top of the new Fragment.

    enter image description here

    I tried with this given below code.

    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    Fragment newFragment = GenericMood.newInstance("a","b");
    
    // Replace whatever is in the fragment_container view with this fragment,
    // and add the transaction to the back stack if needed
    transaction.replace(((ViewGroup)getView().getParent()).getId(), newFragment);
    transaction.addToBackStack(null);
    transaction.commitAllowingStateLoss();
    

    XML files:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/allmoods"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        tools:context="com.moodoff.Moods">
         <Button
            android:text="Button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="64dp"
            android:id="@+id/btn_btn"
            android:height="80dp"
            android:width="100dp"
            android:onClick="putmeoff"
            android:layout_marginLeft="17dp"
            android:layout_marginStart="17dp"/>
    </RelativeLayout>
    

    This is the fragment that is supposed to replace the above:

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:id="@+id/genericmood"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        tools:context="com.moodoff.GenericMood">
        <!-- TODO: Update blank fragment layout -->
    
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#000000"
            android:layout_gravity="fill_horizontal"
            android:id="@+id/floatingButtons"
            >
            <android.support.design.widget.FloatingActionButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="1dp"
                android:layout_marginRight="14dp"
                app:backgroundTint="#ffffff"
                android:layout_alignParentTop="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:src="@drawable/cameraicon"
                android:id="@+id/btn_camera"
                app:fabSize="mini"
                />
        </RelativeLayout>
    </FrameLayout>
    

    Both doesn't work. What to do? UPDATE: After replacing with the proper container the buttons had gone but the new fragment is not getting instantiated properly. I gets a pure blank white screen. enter image description here

    my activity_alltabs.xml looks like this: 
    
    <?xml version="1.0" encoding="utf-8"?>
        <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/main_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            tools:context="com.moodoff.AllTabs">
    
            <android.support.design.widget.AppBarLayout
                android:id="@+id/appbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/AppTheme.AppBarOverlay">
    
                <android.support.design.widget.TabLayout
                    android:id="@+id/tabs"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@android:color/background_dark" />
    
            </android.support.design.widget.AppBarLayout>
    
            <android.support.v4.view.ViewPager
                android:id="@+id/container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    
        </android.support.design.widget.CoordinatorLayout>
    
  • Santanu
    Santanu over 7 years
    Thank you. Its getting added but i don't see any content in thew newly replaced fragment. Its a pure white screen.
  • Santanu
    Santanu over 7 years
    Thanks. But the thing is that i have a tabbed activity ALLTabs.java. Inside that in one of the tabs(let say 1st one) i create a fragment that displays some buttons,. On clicking a button in that fragment, a new fragment would replace that, but i see the buttons in the new fragment from the old fragment.
  • Santanu
    Santanu over 7 years
    my activity_alltabs.xml looks like this:
  • Mike
    Mike over 7 years
    Make sure you are passing the same ID into FragmentTransaction.replace when loading each fragment. Also... I'll edit the answer for something else.
  • Santanu
    Santanu over 7 years
    How to ensure that the first fragment is getting loaded inside that fragment id only as i use replace only once to navigate from 1st fragment to the 2nd. I have used correct container id.