How to avoid adding same fragment to stack
Asked Answered
D

6

8

I need some help. em adding fragment to activity this way. problem is on each call of openFragment it create fragment and add. which is obvious. Question: what modification i do, so it can add fragment only once. on the next call with same fragment tag it will do nothing.

case: press button first time it add fragment and shows. i press again same button it response nothing.

public static void openFragment(Activity activity, Fragment fragment) {

    FragmentManager fragmentManager = ((ActionBarActivity) activity)
            .getSupportFragmentManager();
        FragmentTransaction ftx = fragmentManager.beginTransaction();
        ftx.addToBackStack(fragment.getClass().getSimpleName());
        ftx.setCustomAnimations(R.anim.slide_in_right,
                R.anim.slide_out_left, R.anim.slide_in_left,
                R.anim.slide_out_right);
        ftx.add(R.id.main_content, fragment);
        ftx.commit();
}
Demit answered 19/3, 2015 at 12:16 Comment(1)
D
9

Here's the solution, It will only allow you to add fragment once in stack otherwise it will pop-out the very same fragment from stack.

public static void openFragment(Activity activity, Fragment fragment) {
    String fragmentTag = fragment.getClass().getName();
    FragmentManager fragmentManager= ((ActionBarActivity) activity)
            .getSupportFragmentManager();

    boolean fragmentPopped = fragmentManager
            .popBackStackImmediate(fragmentTag , 0);

    if (!fragmentPopped && fragmentManager.findFragmentByTag(fragmentTag) == null) {

    FragmentTransaction ftx = fragmentManager.beginTransaction();
    ftx.addToBackStack(fragment.getClass().getSimpleName());
    ftx.setCustomAnimations(R.anim.slide_in_right,
            R.anim.slide_out_left, R.anim.slide_in_left,
            R.anim.slide_out_right);
    ftx.add(R.id.main_content, fragment);
    ftx.commit();
  }
}

slide_in_right

<?xml version="1.0" encoding="utf-8"?>
  <set xmlns:android="http://schemas.android.com/apk/res/android"
   android:shareInterpolator="true">
  <translate android:fromXDelta="100%"
    android:toXDelta="0%" android:fromYDelta="0%"
    android:toYDelta="0%" android:duration="200">
  </translate>
</set>

slide_out_right

<?xml version="1.0" encoding="utf-8"?>
   <set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate android:fromXDelta="0%" android:toXDelta="100%"
    android:fromYDelta="0%" android:toYDelta="0%"
    android:duration="200">
  </translate>
</set>

slide_in_left

<?xml version="1.0" encoding="utf-8"?>
  <set xmlns:android="http://schemas.android.com/apk/res/android"
  android:shareInterpolator="true">
  <translate android:fromXDelta="-100%"
    android:toXDelta="0%" android:fromYDelta="0%"
    android:toYDelta="0%" android:duration="200">
  </translate>
</set>

slide_out_left

<?xml version="1.0" encoding="utf-8"?>
 <set xmlns:android="http://schemas.android.com/apk/res/android"
  android:shareInterpolator="true">
  <translate android:fromXDelta="0%"
    android:toXDelta="-100%" android:fromYDelta="0%"
    android:toYDelta="0%" android:duration="200">
  </translate>
</set>

And this is how you call this function:

openFragment(activity, new MyFragment());
Demit answered 28/12, 2015 at 5:37 Comment(1)
Please, how to call the function openFragment(???,newfragment) and the code xml for animation slide...Shagbark
L
7

Use FragmentTransaction.replace() instead of FragmentTransaction.add():

This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.

The first call to FragmentTransaction.replace() will simply add the fragment as there were no fragments to remove.

Lati answered 19/3, 2015 at 12:25 Comment(1)
i can't use replace because of having network operations. so each visit to same fragment it cost me a request again.Demit
V
5

check if fragment is already added or not by using this method:

if(!Fragment.isAdded()){
//add fragment
}
Vendue answered 22/3, 2017 at 10:2 Comment(0)
J
1

Depending on your needs, there are multiple ways to approach this:

  1. Disable or remove the button after it's clicked once.
  2. As @hidro suggested, use replace() instead of add() when calling the FragmentTransaction.
  3. Keep a List of string that will contain the class name of each fragment as it is added to the UI.

E.g.

List<String> fragments = new ArrayList<String>();

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        FragmentTransaction ftx = fragmentManager.beginTransaction();
        ftx.add(R.id.main_content, fragment);
        ftx.commit();
        fragments.add(fragment.getClass().toString());
    }
});

Before adding the fragment using FragmenTransaction.commit() check if its class exists in the list and if it does, don't add it.

Again, these 3 approaches work but which one will pick will depend on your app.

Jigsaw answered 19/3, 2015 at 12:37 Comment(1)
i can't do this to all buttons (disable btn). and replace instead of add isn't good choice because i am doing network operation on each fragment, so it cost me more. i look forward to 3rd if not find any better aproach. thanksDemit
F
0

You can use show() method of fragment transaction

 FragmentManager fragmentManager = ((ActionBarActivity) activity)
            .getSupportFragmentManager();
        FragmentTransaction ftx = fragmentManager.beginTransaction();

        ftx.setCustomAnimations(R.anim.slide_in_right,
                R.anim.slide_out_left, R.anim.slide_in_left,
                R.anim.slide_out_right);
    if(!fragment.isAdded())
    {
    //add fragment;
ftx.add(R.id.main_content, fragment).comit();
    }
    else
    {
   ftx.show(fragment).comit();
    }

Updated

Ferwerda answered 19/3, 2015 at 12:29 Comment(2)
I used it. but not working. can you please modify this check according to my code. thanksDemit
I modified and i read above as you are making network calls so it will make a network call only once when fragment is created and once it is created it is only going to show it next time. Make network call in if statement.Ferwerda
S
0

To add a fragment only once,

You need to check every time before adding the fragment to backstack, that if previously it is already added or not. If it is added already, then you should pop that entry and add another entry.

So, you can do this using :

boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);

If fragmentPopped is true then there was a fragment added to backstack and itt is popped and you can add your fragment now to backstack. It is safe to call :

ftx.addToBackStack(fragment.getClass().getSimpleName());

If fragmentPopped is false then there was not any fragment added in backstack

Very nice information you can get : here

Simper answered 19/3, 2015 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.