【问题标题】:How to avoid adding same fragment to stack如何避免将相同的片段添加到堆栈
【发布时间】:2015-03-19 12:16:09
【问题描述】:

我需要一些帮助。以这种方式将片段添加到活动中。问题出在每次调用 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();
}

【问题讨论】:

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


【解决方案1】:

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

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

【讨论】:

  • 请问如何调用函数openFragment(???,newfragment)和动画幻灯片的xml代码...
【解决方案2】:

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

这与调用remove(Fragment) 基本相同,对所有当前添加的片段使用相同的containerViewId 添加,然后使用此处给出的相同参数添加add(int, Fragment, String)

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

【讨论】:

  • 我不能使用替换,因为有网络操作。所以每次访问同一个片段都会再次花费我一次请求。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    根据您的需要,有多种方法可以解决此问题:

    1. 单击一次后禁用或删除按钮。
    2. 正如@hidro 建议的那样,在调用 FragmentTransaction 时使用 replace() 而不是 add()。
    3. 保留一个字符串列表,其中包含添加到 UI 中的每个片段的类名。

    例如

    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 种方法有效,但选择哪一种取决于您的应用。

    【讨论】:

    • 我无法对所有按钮执行此操作(禁用 btn)。并且替换而不是添加不是好的选择,因为我正在对每个片段进行网络操作,所以它花费了我更多。如果找不到更好的方法,我期待第三次。谢谢
    【解决方案5】:

    只添加一次片段,

    在将片段添加到 backstack 之前,您需要每次检查, 如果以前它已经添加或不添加。如果已经添加, 那么您应该弹出该条目并添加另一个条目。

    所以,您可以使用:

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

    如果fragmentPoppedtrue,那么有一个片段被添加到 backstack 并且它被弹出,你现在可以将你的片段添加到 backstack。打电话是安全的:

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

    如果fragmentPoppedfalse,则回栈中没有添加任何片段

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

    【讨论】:

      【解决方案6】:

      可以使用片段事务的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();
          }
      

      更新

      【讨论】:

      • 我用过。但不工作。你能根据我的代码修改这个检查吗?谢谢
      • 我修改并阅读了上面的内容,因为您正在进行网络调用,因此它只会在创建片段时进行一次网络调用,并且一旦创建它只会在下次显示它。在 if 语句中进行网络调用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-05
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多