Reputation: 893
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
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
.
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>
Upvotes: 9
Views: 19419
Reputation: 116
put your next fragment UI elements in Card View. define a LinearLayout or other view groups as root and inside this root create a Card view and put your other elements in Card View . when you inflate it in Card View then the hole of new fragment inflate on the previous fragment.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parenter code hereent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="-20dp"
app:cardCornerRadius="20dp">
......... your UI Elements .......
//, for example, define other LinearLayout inside the Card View
and put other elements inside it like TextView, Button and
so on...
</androidx.cardview.widget.CardView>
</LinearLayout>
Upvotes: 0
Reputation: 5582
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.
Upvotes: 3
Reputation: 316
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.
Upvotes: 5
Reputation: 1774
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>
Upvotes: 1
Reputation: 182
Just make buttons setVisibility(View.GONE) in your activity when that fragment is begin transaction.
Upvotes: 0
Reputation: 347
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();
Upvotes: 1
Reputation: 419
The problem was the the container ID that was passing to the replace method was the ID of the fragment that was replacing, not the ID of the fragment container. This seems to explain why some of the original fragment controls were remaining after the replace - that entire fragment wasn't being replaced.
Please change it to get the fragment container view ID, and it will work! Here's the code:
transaction.replace(((ViewGroup)(getView().getParent())).getId(), fragment);
I found the answer for getting the container view ID of a fragment here, Get fragment's container view id.
Upvotes: 0
Reputation: 3632
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.
Upvotes: 3