如何避免将相同的片段添加到堆栈中

时间:2015-03-19 12:16:09

标签: android android-fragments stack android-fragmentactivity fragmentmanager

我需要一些帮助。以这种方式将片段添加到活动中。问题是每次调用openFragment时都会创建片段并添加。这很明显。问题:我做了什么修改,所以它只能添加片段一次。在具有相同片段标签的下一次调用中,它将无效。

案例:第一次按下按钮添加片段并显示。我再次按下相同的按钮它没有任何反应。

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();
}

6 个答案:

答案 0 :(得分:9)

这是解决方案,它只允许你在堆栈中添加一次片段,否则它会从堆栈中弹出相同的片段。

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>

这就是你如何称呼这个功能:

openFragment(activity, new MyFragment());

答案 1 :(得分:5)

使用FragmentTransaction.replace()代替FragmentTransaction.add()

  

这与为所有当前添加的片段调用remove(Fragment)基本相同,这些片段使用相同的containerViewId添加,然后add(int, Fragment, String)添加了相同的参数。

第一次调用FragmentTransaction.replace()只会添加片段,因为没有要删除的片段。

答案 2 :(得分:4)

使用此方法检查片段是否已添加:

if(!Fragment.isAdded()){
//add fragment
}

答案 3 :(得分:1)

根据您的需求,有多种方法可以解决这个问题:

  1. 点击一次后禁用或删除按钮。
  2. 正如@hidro建议的那样,在调用FragmentTransaction时使用replace()而不是add()。
  3. 保留一个字符串列表,该字符串将包含添加到UI中的每个片段的类名。
  4. 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());
        }
    });
    

    在使用FragmenTransaction.commit()添加片段之前,请检查列表中是否存在类,如果存在,请不要添加它。

    同样,这3种方法都有效,但选择的方法取决于您的应用。

答案 4 :(得分:0)

您可以使用片段事务的show()方法

 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();
    }

更新

答案 5 :(得分:0)

仅添加片段一次,

  

每次将片段添加到backstack之前都需要检查,   如果之前已经添加或未添加。如果已添加,   然后你应该弹出那个条目并添加另一个条目。

所以,你可以这样做:

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

如果fragmentPopped 为真,则会在backstack中添加一个片段并弹出它,您现在可以将片段添加到Backstack中。可以安全地致电:

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

如果fragmentPopped false ,那么backstack中没有添加任何片段

您可以获得非常好的信息:here