Fragment is not being replaced but put on top of the previous one
Asked Answered
K

16

115

Activity:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

Fragment1 fragment = new Fragment1();
Fragment2 fragment2 = new Fragment2();

transaction.replace(R.id.Fragment1, fragment);
transaction.addToBackStack(null);
transaction.commit();

FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
transaction2.replace(R.id.Fragment1, fragment2);
transaction2.addToBackStack(null);
transaction2.commit();

Code in the view:

<fragment
    android:id="@+id/Fragment1"
    android:name="com.landa.fragment.Fragment1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/include1" /> 

The problem is, the content doesn't really get replaced - it gets put on top (so it overlaps).

When I click back, the first fragment gets shown properly (without the second), but initially both are visible (I want only the last one to be visible).

What am I missing here?

Kreiker answered 11/2, 2013 at 10:32 Comment(1)
In my case the problem was due to the fact that I was not using the appropriate id of the container view, i.e. I was not passing the correct containerViewId (in the replace method).Clobber
T
151

You are doing two things wrong here:

  1. You cannot replace a fragment that is statically placed in an xml layout file. You should create a container (e.g. a FrameLayout) in the layout and then add the fragment programatically using FragmentTransaction.

  2. FragmentTransaction.replace expects the id of the container that contains the fragment and not the id of the fragment as the first parameter. So you should pass the first argument as the id of the container that you added the first fragment to.

You can refer to this link for more details.

Track answered 11/2, 2013 at 10:50 Comment(5)
Using FrameLayout as a container is better than using LinearLayout.Schaal
Using an empty FrameLayout in Activity solved my problem tooMccubbin
It works doing this. But then when I start my application and immediately press the back button, I end up in a state where the fragment is empty, instead of exiting the app?Assuage
@Assuage Omit the addTobackStack(..) when doing your transaction for the first time. This will avoid placing the empty FrameLayout container onto the back stack. You will still be able to navigate back to the fragment your adding.Enervate
Here is a great video that demonstrates your explanation. youtube.com/watch?v=EbcdMxAIr54Janeth
M
33

I had a similar problem but my issue was that I was using two different Fragment managers: One from getSupportFragmentManager() and one from getFragmentManager(). If I added one fragment with the SupportFragmentManager and then tried replacing the fragment with the FragmentManager, the fragment would just get added on top. I needed to change the code so that the same FragmentManager would be used and that took care of the issue.

Microelement answered 27/5, 2014 at 20:47 Comment(0)
B
17

The android developer site suggests the use of a FrameLayout to load fragments dynamically at run-time. You have hard-coded the fragment in your xml file. So it cannot be removed at run-time as mentioned in this link:

http://developer.android.com/training/basics/fragments/creating.html

this link shows how to add fragments through your program:

http://developer.android.com/training/basics/fragments/fragment-ui.html

Berliner answered 11/2, 2013 at 10:50 Comment(0)
C
7

I had the same problem and saw all the answers, but none of them contained my mistake! Before trying to replace the current fragment, I was showing the default fragment in the xml of the container activity like this:

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

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="....ShopFragment"
        android:id="@+id/fragment"
        tools:layout="@layout/fragment_shop" />
</FrameLayout>

after that, although i was passing the FrameLayout to the fragmentTransaction.replace() but i had the exact problem. it was showing the second fragment on top of the previous one.

The problem fixed by removing the fragment from the xml and showing it programmatically in the onCreate() method of the container activity for the default preview on the start of the program like this:

    fragmentTransaction = getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_frame_layout,new ShopFragment());
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();

and the container activity xml:

<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
Chare answered 22/8, 2016 at 14:23 Comment(0)
A
5

You can clear backStack before replacing fragments:

    FragmentManager fm = getActivity().getSupportFragmentManager();

    for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
        fm.popBackStack();
    }

    // replace your fragments
Assassinate answered 11/2, 2013 at 10:47 Comment(2)
the problem is that he has declared the fragment in his xml layout file. Hence it cannot be removed/replaced at run-time.Berliner
this worked for me, trying to replace a fragment without clearing the backstack seemed to leave the most recent backstack entry over the top of any other fragment.Grof
M
3
<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:windowBackground">
//Add fragment here
</FrameLayout>

Add android:background="?android:windowBackground"> to the container in which your fragment resides. In in my case I added a FrameLayout, that should help.

Metope answered 19/11, 2019 at 10:59 Comment(0)
G
1

I agree with Sapan Diwakar's answer. But I have found a workaround on how to do this.

First, in your activity(e.g. activity_main), where you have all the layouts, Add a FrameLayout. It's height and width should be match parent. Also, give it an id.

Now, in your fragment which is going to replace the current layout, call onPause() and onResume(). Initialise all the all the inner containers in View. And set their visibility to GONE in onResume() and VISIBLE in onPause().

NOTE: Not the FrameLayout which you are replacing with this fragment.

Suppose you have ViewPager, TabLayout, ImageView and a custom <fragment> in activity_main.xml. Add, a FrameLayout as mentioned above.

In abcFragment.java, in onClick() function, add addToBackstack(null) in transaction.

Example code:

in xyzFragment, which is going to replace abcFragment(and everything shown in activity_main.xml), do this

@Override
    public void onResume() {
        super.onResume();

    // On resume, make everything in activity_main invisible except this fragment.
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.GONE);
    viewPager.setVisibility(View.GONE);
    miniPlayerFragment.setVisibility(View.GONE);
}

@Override
public void onPause() {
    super.onPause();

    // Make everything visible again
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.VISIBLE);
    viewPager.setVisibility(View.VISIBLE);
    miniPlayerFragment.setVisibility(View.VISIBLE);
}

Happy coding!

Gothar answered 16/9, 2015 at 17:33 Comment(0)
R
1

Use a container instead of using fragment

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hello World!" />

Now in MainActivity

if(condition)
    getFragmentManager().beginTransaction().replace(R.id.container,new FirstFragment()).commit();                    
else
    getFragmentManager().beginTransaction().replace(R.id.container, new SecondFragment()).commit();

Please note that your fragment class should import 'android.app.Fragment' Make sure, that you use "support.v4" or the "original" implementations and do not mix them. I was getting this problem because I had mixed them.

Rodriquez answered 22/2, 2016 at 6:50 Comment(0)
P
0

Thank you to Sapan Diwakar and others. This answer helped me. I simply created a RelativeLayout without a fragment inside it, used the RelativeLayout as a parent or group view, specified that group view in the transaction to replace, and it worked.

Code:

getSupportFragmentManager().beginTransaction()
                            .replace(R.id.content_group_view, itemDetailFragment).commit();

XML:

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

 </RelativeLayout>
Phrensy answered 21/10, 2015 at 22:29 Comment(0)
A
0

You can use setTransition method from FragmentTransaction to fix overlapping issue.

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
Autacoid answered 6/5, 2016 at 15:29 Comment(0)
C
0

In Oncreate ()

  BaseFragmentloginpage fragment = new BaseFragmentloginpage();
            android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment);
            fragmentTransaction.isAddToBackStackAllowed();
            fragmentTransaction.commit();

now this will be always your default fragment ...if you add fragment in xml layout it will always overlap , so set initial content with fragment at run time

Charlottetown answered 16/2, 2017 at 8:49 Comment(0)
R
0

i had same problem after using this problem solved

  1. Take frame layout where u are replacing ur fragment

    <FrameLayout
                    android:id="@+id/fragment_place"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />
    
  2. and code for replacement

    public void selectFrag(View view) {
    Fragment fr;
    
      if(view == findViewById(R.id.button2))
    {
         fr = new FragmentTwo();
    
     }else {
         fr = new FragmentOne();
     }
     FragmentManager fm = getFragmentManager();
     FragmentTransaction fragmentTransaction = fm.beginTransaction();
     fragmentTransaction.replace(R.id.fragment_place, fr);
     fragmentTransaction.commit();
    

if you want whole example i will send you just comment me......

Redbreast answered 6/4, 2017 at 7:5 Comment(0)
I
0

I also had the same issue, but it was because I had not changed the background color of the fragment that I was trying add to my framelayout.

Try doing this, with layout_height and layout_width set to match_parent

Interscholastic answered 4/6, 2018 at 15:5 Comment(0)
H
0

I once had this problem and found out that it was because I had accidentally deleted the android:background attribute that is missing on your xml code. I believe it works like when you're painting a wall, android:background is the color that the wall will be and the other views are placed on top of that base color. When you don't paint the wall prior to positioning your views they will be on top of what was already in that wall, in your case, your other fragment. Don't know if that will help you though, good luck.

Haematic answered 4/7, 2019 at 22:55 Comment(0)
I
0

I have tried above all the case and try to fix the issue but still not got solution. I don't know why its not working for me. I agree with above answers because so many agree with it.

I am just extending the answer and below is the way which is working for me.

I have added this property android:clickable="true" in top parent layout on fragment.xml file.

I hope someone will get help.

Invar answered 18/10, 2019 at 12:8 Comment(0)
U
0

Check your frame layout ID and replace it as below

fragmentTransactionChange = MainActivity.this.getSupportFragmentManager().beginTransaction();
fragmentTransactionChange.replace(R.id.progileframe, changeFragment);
fragmentTransactionChange.addToBackStack(null);
fragmentTransactionChange.commit();
Ultracentrifuge answered 5/8, 2020 at 9:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.