0

私は2つのフラグメントを切り替える必要がある特別な使用例を持っています。私が抱えている問題は、それを維持する必要がある第2の断片のためであり、そのために働いていると思われる唯一のことは、それをBackStackに追加することだけです。フラグメントのバックスタックとトグル

私はフラグメントを置き換えるためにサポートフラグメントマネージャに依存している:onBackPressed()オーバーライドと組み合わせて

public void toggle() { 
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container); 
    if (fragment instanceof FragmentB && null != fragmentA) { 
     // fragment B is visible - we should show fragment A 

     getSupportFragmentManager().beginTransaction() 
            .setCustomAnimations(R.anim.frag_fade_in, R.anim.frag_fade_out, 
                 R.anim.frag_fade_in, R.anim.frag_fade_out) 
            .replace(R.id.fragment_container, fragmentA) 
            .commit(); 
    } else if (fragment instanceof FragmentA && null != fragmentB) { 
     // fragment A is visible - we should show fragment B 

     boolean isRestored = false; 
     fragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAG_B); 
      if (null != fragment) { 
       // Restore fragment state from the BackStack 
       fragmentB = (FragmentB) fragment; 
       isRestored = true; 
      } 

     FragmentTransaction transaction = getSupportFragmentManager().beginTransaction() 
                     .setCustomAnimations(R.anim.frag_fade_in, 
                           R.anim.frag_fade_out, 
                           R.anim.frag_fade_in, 
                           R.anim.frag_fade_out); 

     transaction.replace(R.id.fragment_container, fragmentB, TAG_FRAG_B); 
     if(!isRestored){ 
      transaction.addToBackStack(TAG_FRAG_B) 
     } 
     transaction.commit(); 
    } else { 
     // Just pop any fragments that were added - usually we won't get in here 
     getSupportFragmentManager().popBackStack(); 
    } 
} 

この:

@Override 
public void onBackPressed() { 
    if (isCurrentFragmentB()) { 
     toggle(); 
    } else { 
     // Back key was pressed and we are on fragment A - at this state we simply want to go back to the 
     // previous section 
     super.onBackPressed(); 
    } 
} 

この実装を使用して、私は私がフラグメントBを再利用することを確認してください毎回ゼロから作成されたようには見えないように状態を維持してください。また、私が戻ったときには、フラグメントBからフラグメントAだけでなく、フラグメントAからフラグメントBに行くことができます。

私が遭遇した問題は、super.onBackPressed();が呼び出され、複数のフラグメントが追加された実際に、私は一度に一つの活性フラグメントをしたいと)フラグメントマネージャを介して、それは例外がスローされます:アクティブなフラグメントはFragmentAある場合にのみ

java.lang.IllegalStateException: Fragment already added: FragmentA{af9c26b #0 id=0x7f0e00d3} 

これが起こっています。私はこれがBackStackの実装のためであるという疑いがありますが、私が言ったように、私は2番目のものを永続させたいだけです。

どうすればこの問題を解決できますか?私は何かを欠いている?

答えて

0

私は少しハックリですが、このための回避策を実装することができました。

FragmentBの状態を維持する必要があるので、私はそれをBackStackに追加する必要がありますが、これはonBackPressed()が呼び出されたときにどのような遷移が実際に元に戻されるかに影響します。

public void toggle() { 
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container); 

    @SuppressLint("CommitTransaction") FragmentTransaction transaction = 
       getSupportFragmentManager().beginTransaction() 
              .setCustomAnimations(R.anim.frag_fade_in, R.anim.frag_fade_out, 
                   R.anim.frag_fade_in, R.anim.frag_fade_out); 

    if (fragment instanceof FragmentB && null != fragmentA) { 
     // fragment B is visible - we should show fragment A 

     fragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAG_A); 
     if (null != fragment) { 
      // Restore fragment state from the BackStack 
      fragmentA = (FragmentA) fragment; 
     } 

     // Replace current fragment with fragment A and commit the transaction 
     transaction.replace(R.id.fragment_container, fragmentA, TAG_FRAG_A).commit(); 
    } else if (fragment instanceof FragmentA && null != fragmentB) { 
     // fragment A is visible - we should show fragment B 

     fragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAG_B); 
      if (null != fragment) { 
       // Restore fragment state from the BackStack 
       fragmentB = (FragmentB) fragment; 
      } 

     // Replace current fragment with fragment B 
     transaction.replace(R.id.fragment_container, fragmentB, TAG_FRAG_B); 

     if (null == fragment) { 
       // No entry of the fragment B in the BackStack, we want to add it for future uses 
       transaction.addToBackStack(TAG_FRAG_B); 
      } 

      // Commit the transaction 
      transaction.commit(); 
    } else { 
     // Just pop any fragments that were added - usually we won't get in here 
     getSupportFragmentManager().popBackStack(); 
    } 
} 

これを回避するために、私はそのような場合も

@Override 
public void onBackPressed() { 
    if (isCurrentFragmentB()) { 
     toggle(); 
    } else if (isCurrentFragmentA()) { 
     getSupportFragmentManager().popBackStackImmediate(TAG_FRAG_A, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
     // Special case - because we added the fragment B to the BackStack in order to easily resume it's state, 
     // this will fail as it will actually try to add fragment A again to the fragment manager (it 
     // will try to reverse the last transaction) 
     super.finish(); 
    } else { 
     // Usual flow - let the OS decide what to do 
     super.onBackPressed(); 
    } 
} 

をバックプレス用のロジックを更新し、手動で処理するために持っていた、私はトグル方法を少し最適化されました私はこれが同様の流れを必要とする他の人を助けることができると思います。

PS:私が保持したいフラグメントはSupportMapFragmentです。そのため、マップを常に表示し直したり、再センタリングしたり、表示するたびにデータを入力したりする必要はありません。

関連する問題