Replace one fragment with an another fragment
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>
Related videos on Youtube
Comments
-
Santanu almost 2 years
I want to replace an old
Fragment
with a newFragment
, but i still get the buttons of the oldFragment
that is still visible in the new fragment.In the old one, on a button click
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.allmoodsFragment
still visible on top of the newFragment
.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.
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 over 7 yearsThank you. Its getting added but i don't see any content in thew newly replaced fragment. Its a pure white screen.
-
Santanu over 7 yearsThanks. 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 over 7 yearsmy activity_alltabs.xml looks like this:
-
Mike over 7 yearsMake sure you are passing the same ID into FragmentTransaction.replace when loading each fragment. Also... I'll edit the answer for something else.
-
Santanu over 7 yearsHow 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.