2013-08-01 4 views
0

J'utilise MainActivity pour gérer l'affichage de plusieurs fragments. J'ai une méthode showFragment qui itère à travers mon tableau de fragments et les montre/les cache, et définit le backstack en conséquence. Le problème est que chaque fois que j'appuie sur le bouton de retour, le HomeFrag s'affiche, avec tous les autres fragments entassés en dessous. J'ai été sous l'impression de la documentation que le bouton de retour va inverser la dernière transaction (tout ce qui a été ajouté avant la validation). Quelqu'un peut-il expliquer pourquoi cela pourrait causer ce comportement inattendu? Voici mon activité principale. Les fragments sont tous définis dans activity_main.xml:addToBackStack affiche tous les fragments

public class MainActivity extends MenuBaseActivity { 
    private static final int HOME = 0; 
    private static final int WRITE = 1; 
    private static final int UPLOAD = 2; 
    private static final int SHARE = 3; 
    private static final int SNAP = 4; 
    private static final int POSITION = 5; 

    private static final int FRAGMENT_COUNT = POSITION + 1; 

    /** The current fragment being displayed **/ 
    private int mCurrentFragment = -1; 

    private Fragment[] fragments = new Fragment[FRAGMENT_COUNT]; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.activity_main); 

     FragmentManager fm = getSupportFragmentManager(); 

     fragments[HOME] = fm.findFragmentById(R.id.homeFrag); 
     fragments[WRITE] = fm.findFragmentById(R.id.writeFrag); 
     fragments[UPLOAD] = fm.findFragmentById(R.id.uploadFrag); 
     fragments[SHARE] = fm.findFragmentById(R.id.shareFrag); 
     fragments[SNAP] = fm.findFragmentById(R.id.snapFrag); 
     fragments[POSITION] = fm.findFragmentById(R.id.positionFrag); 

     // If no fragments are currently being displayed, show the home frag 
     if(mCurrentFragment == -1) { 
      showFragment(0,true); 
     } 


    } 

    /* 
    * Handles the click event for all navigation buttons (navOnClick) in the fragments. 
    */ 
    //TODO: Tag navigation with text strings instead of integers 
    public void navOnClick(View v) { 

     Object objectTag = v.getTag(); 
     int tag = Integer.valueOf(objectTag.toString()); 
     showFragment(tag, true); 
    } 


    public void showFragment(int fragmentIndex, boolean addToBackStack) { 

     Log.v(Constants.getLogTag(), "Main: fragmentIndex:" + fragmentIndex + " backstack:" + addToBackStack); 

     FragmentManager fm = getSupportFragmentManager(); 
     FragmentTransaction ft = fm.beginTransaction(); 
     //ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right); 

     for (int i = 0; i < fragments.length; i++) { 
      if (i == fragmentIndex) { 
       ft.show(fragments[i]); 
       } else { 
       ft.hide(fragments[i]); 
      } 
     } 

     if (addToBackStack) { 
      Log.v(Constants.getLogTag(), "Main: Adding to backstack"); 
      ft.addToBackStack(null); 
     } 

     //Update the current fragment identifier 
     mCurrentFragment = fragmentIndex; 

     ft.commit(); 
    } 


} 
+0

Vous Itère votre tableau et cachant chaque fragment dans une transaction, de sorte que lorsque vous appuyez sur la backbutton, il unhides tous à la fois. – btse

+0

Il semble désordonné là-bas. Changez toute votre logique, ne faites pas comme ça. –

+1

@ M-WaJeEh Peut-être que vous pourriez suggérer un refactor rapide, je ne pense pas que vous êtes un commentaire est très utile tel quel. – jwBurnside

Répondre

1

Je n'ai pas testé personnellement, mais laissez-moi savoir comment cela fonctionne. J'ai effectivement décidé de garder le tableau afin que nous puissions cacher correctement chaque fragment lorsque l'activité est démarrée pour la première fois. J'ai changé juste quelques petites choses qui devraient régler votre problème. Il n'est pas nécessaire de cacher chaque fragment à chaque fois dans une boucle. Vous devriez seulement devoir cacher le fragment courant chaque fois.

public class MainActivity extends MenuBaseActivity { 
    private static final int HOME = 0; 
    private static final int WRITE = 1; 
    private static final int UPLOAD = 2; 
    private static final int SHARE = 3; 
    private static final int SNAP = 4; 
    private static final int POSITION = 5; 

    /** The current fragment being displayed **/ 
    private int mCurrentFragment = HOME; 

    private Fragment[] fragments = new Fragment[FRAGMENT_COUNT]; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.activity_main); 

     FragmentManager fm = getSupportFragmentManager(); 
     FragmentTransaction ft = fm.beginTransaction(); 

     fragments[HOME] = fm.findFragmentById(R.id.homeFrag); 
     fragments[WRITE] = fm.findFragmentById(R.id.writeFrag); 
     fragments[UPLOAD] = fm.findFragmentById(R.id.uploadFrag); 
     fragments[SHARE] = fm.findFragmentById(R.id.shareFrag); 
     fragments[SNAP] = fm.findFragmentById(R.id.snapFrag); 
     fragments[POSITION] = fm.findFragmentById(R.id.positionFrag); 

     // Hide all of the fragments except for the home fragment 
     for (int i = WRITE; i < fragments.length; i++) { 
      ft.hide(fragments[i]); 
     } 

     ft.commit(); 
    } 

    /* 
    * Handles the click event for all navigation buttons (navOnClick) in the fragments. 
    */ 
    //TODO: Tag navigation with text strings instead of integers 
    public void navOnClick(View v) { 

     Object objectTag = v.getTag(); 
     int tag = Integer.valueOf(objectTag.toString()); 
     showFragment(tag, true); 
    } 


    public void showFragment(int fragmentIndex, boolean addToBackStack) { 

     Log.v(Constants.getLogTag(), "Main: fragmentIndex:" + fragmentIndex + " backstack:" + addToBackStack); 

     FragmentManager fm = getSupportFragmentManager(); 
     FragmentTransaction ft = fm.beginTransaction(); 

     // I changed this part too. You will probably want to implement it this way 
     // if you want to also see an animation when hitting the back button. I will 
     // leave it up to you as an exercise to figure out how the other animator 
     // files should be constructed 
     ft.setCustomAnimations(R.animator.slide_in_right, R.animator.slide_out_left, 
           R.animator.slide_in_left, R.animator.slide_out_right); 

     ft.hide(fragments[mCurrentFragment]); 
     ft.show(fragments[fragmentIndex]); 

     if (addToBackStack) { 
      Log.v(Constants.getLogTag(), "Main: Adding to backstack"); 
      ft.addToBackStack(null); 
     } 

     //Update the current fragment identifier 
     mCurrentFragment = fragmentIndex; 

     ft.commit(); 
    } 
} 
+0

Appréciez l'aide. Bien que votre exemple fonctionne pour l'essentiel, je m'attends à rencontrer des problèmes de tête, car j'utilise également des activités intégrées de caméra et des bibliothèques tierces. Plus les fragments semblent être exagérés. Aller à tout convertir en une activité et utiliser seulement des fragments si j'ai besoin d'un changement de mise en page pour les autres appareils. – jwBurnside

+0

@jwburnside Cela me semble bon.Juste à titre de note, je pense que la mise en page initiale de votre application était étrange. Si vous envisagiez d'utiliser chaque fragment comme son propre écran, vous devriez traiter chaque fragment essentiellement comme une activité et les créer tous par programmation, c'est-à-dire créer une classe de fragment distincte pour chaque fragment. Les coder en dur au format XML et les cacher ensuite est une façon étrange de faire les choses et cela vous empêche de détruire les fragments si besoin est. Juste quelque chose à garder à l'esprit dans le futur. – btse

Questions connexes