Manipulation du titre ActionBar avec la stack arrière du fragment?

J’ai une Activity que je charge dans un ListFragment et, en cliquant dessus, elle explore un niveau et un nouveau type de ListFragment est affiché, remplaçant le premier (en utilisant la méthode showFragment ci-dessous). Ceci est placé sur la stack arrière.

Au début, l’activité affiche le titre par défaut dans la barre d’action (c.-à-d. Qu’elle est définie automatiquement en fonction de l’ android:label l’application).

Lorsque vous affichez la liste du niveau suivant dans la hiérarchie, le nom de l’élément sur lequel vous avez cliqué doit devenir le titre de la barre d’action.

Cependant, lorsque vous appuyez sur Retour , j’aimerais que le titre par défaut d’origine soit restauré. Ce n’est pas quelque chose que FragmentTransaction connaît, donc le titre n’est pas restauré.

J’ai vaguement lu à propos de FragmentBreadCrumbs , mais cela semble nécessiter l’utilisation d’une vue personnalisée. J’utilise ActionBarSherlock et je préférerais ne pas avoir ma propre vue de titre personnalisée.

Quelle est la meilleure façon de le faire? Est-ce possible sans une charge de code passe-partout et de garder la trace des titres affichés en cours de route?


 protected void showFragment(Fragment f) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.fragment_container, f); ft.addToBackStack(null); ft.commit(); } 

Dans chaque fragment et chaque activité, je change le titre comme ceci. De cette façon, le titre actif sera toujours correct:

 @Override public void onResume() { super.onResume(); // Set title getActivity().getActionBar() .setTitle(R.ssortingng.thetitle); } 

Il y a des cas où onResume n’est pas appelé à l’intérieur des fragments. Dans certains de ces cas, nous pouvons utiliser:

 public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if(isVisibleToUser) { // Set title getActivity().getActionBar() .setTitle(R.ssortingng.thetitle); } } 

Comme la réponse originale est assez ancienne, cela pourrait aussi être utile. Comme l’indique la documentation, il est possible que vous souhaitiez enregistrer un listener pour écouter les modifications de la stack arrière dans l’ Activity hébergement:

 getSupportFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { public void onBackStackChanged() { // Update your UI here. } }); 

Ensuite, identifiez la situation dans la méthode de rappel et définissez un titre approprié, sans accéder à la ActionBar partir du Fragment .

C’est une solution plus élégante car le Fragment n’a pas besoin de connaître l’existence d’ ActionBar et l’ Activity est généralement l’endroit qui gère le système de sécurité, ce qui semble plus approprié. Fragment ne doit être considéré à tout moment que par son propre contenu et non par l’environnement.

Plus d’informations sur le sujet dans la documentation .

Laissez l’activité de contrôle faire tout le travail comme suit:

Écoutez les événements de backstack (dans onCreate () de l’activité):

 // Change the title back when the fragment is changed getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { Fragment fragment = getFragment(); setTitleFromFragment(fragment); } }); 

Récupère le fragment actuel du conteneur:

 /** * Returns the currently displayed fragment. * @return * Fragment or null. */ private Fragment getFragment() { Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.container); return fragment; } 

Définissez le fragment dans la vue de contenu:

 private void setFragment(Fragment fragment, boolean addToBackStack) { // Set the activity title setTitleFromFragment(fragment); . . . } 

Warpzit a raison. Cela résout également le problème de titre lorsque l’orientation de l’appareil est modifiée. Aussi, si vous utilisez le support v7 pour la barre d’action, vous pouvez obtenir la barre d’action de fragment comme ceci:

 @Override public void onResume() { super.onResume(); ((ActionBarActivity)getActivity()).getSupportActionBar().setTitle("Home"); } 

Il est préférable de laisser le système d’exploitation faire le maximum de travail. En supposant que chaque fragment est correctement nommé à l’aide de .addToBackStack (“title”), vous pouvez alors remplacer onBackPressed pour obtenir le comportement souhaité:

 // this example uses the AppCompat support library // and works for dynamic fragment titles @Override public void onBackPressed() { FragmentManager fragmentManager = getSupportFragmentManager(); int count = fragmentManager.getBackStackEntryCount(); if (count <= 1) { finish(); } else { String title = fragmentManager.getBackStackEntryAt(count-2).getName(); if (count == 2) { // here I am using a NavigationDrawer and open it when transitioning to the initial fragment // a second back-press will result in finish() being called above. mDrawerLayout.openDrawer(mNavigationDrawerFragment.getView()); } super.onBackPressed(); Log.v(TAG, "onBackPressed - title="+title); getSupportActionBar().setTitle(title); } } 

J’utilise une solution similaire à l’ approche de Lee , mais en remplaçant la méthode onBackStackChanged() place.

Je commence par définir le nom du fragment lors de l’ajout de la transaction à la stack arrière.

 getSupportFragmentManager().beginTransaction() .replace(R.id.frame_content, fragment) .addToBackStack(fragmentTitle) .commit(); 

Ensuite, je remplace la méthode onBackStackChanged() et j’appelle setTitle() avec le dernier nom de l’entrée backstack.

 @Override public void onBackStackChanged() { int lastBackStackEntryCount = getSupportFragmentManager().getBackStackEntryCount() - 1; FragmentManager.BackStackEntry lastBackStackEntry = getSupportFragmentManager().getBackStackEntryAt(lastBackStackEntryCount); setTitle(lastBackStackEntry.getName()); } 

Utiliser la méthode des fragments:

 @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 

Il est appelé sur chaque apparence de fragment, mais ce n’est pas le cas sur onResume.

La meilleure approche consiste à utiliser la méthode d’interface fournie par Android OnBackStackChangedListener onBackStackChanged ().

Disons que nous avons un tiroir de navigation avec 4 options vers lesquelles l’utilisateur peut naviguer. Dans ce cas, nous aurons 4 fragments. Voyons d’abord le code et ensuite je vais expliquer le travail.

  private int mPreviousBackStackCount = 0; private Ssortingng[] title_name = {"Frag1","Frag2","Frag3","Frag4"}; Stack mFragPositionTitleDisplayed; public class MainActivity extends ActionBarActivity implements FragmentManager.OnBackStackChangedListener @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); .... .... .... getSupportFragmentManager().addOnBackStackChangedListener(this); mFragPositionTitleDisplayed = new Stack<>(); } public void displayFragment() { Fragment fragment = null; String title = getResources().getString(R.string.app_name); switch (position) { case 0: fragment = new Fragment1(); title = title_name[position]; break; case 1: fragment = new Fragment2(); title = title_name[position]; break; case 2: fragment = new Fragment3(); title = title_name[position]; break; case 3: fragment = new Fragment4(); title = title_name[position]; break; default: break; } if (fragment != null) { FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.container_body, fragment) .addToBackStack(null) .commit(); getSupportActionBar().setTitle(title); } } @Override public void onBackStackChanged() { int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount(); if(mPreviousBackStackCount >= backStackEntryCount) { mFragPositionTitleDisplayed.pop(); if (backStackEntryCount == 0) getSupportActionBar().setTitle(R.ssortingng.app_name); else if (backStackEntryCount > 0) { getSupportActionBar().setTitle(mFragPositionTitleDisplayed.peek()); } mPreviousBackStackCount--; } else{ mFragPositionTitleDisplayed.push(title_name[position]); mPreviousBackStackCount++; } } 

Dans le code montré, nous avons la méthode displayFragment (). J’affiche ici le fragment sur la base de l’option choisie dans le tiroir de navigation. La position de la variable correspond à la position de l’élément cliqué dans ListView ou RecyclerView dans le tiroir de navigation. J’ai défini le titre de la barre d’action en conséquence avec getSupportActionBar.setTitle (title), où le titre stocke le nom du titre approprié.

Chaque fois que nous cliquons sur l’élément du tiroir de navigation, un fragment est affiché en fonction de l’élément cliqué sur l’utilisateur. Mais à l’arrière, ce fragment est ajouté au backstack et la méthode onBackStachChanged () est touchée. Ce que j’ai fait, c’est que j’ai créé une variable mPreviousBackStackCount et que je l’ai initialisée à 0. J’ai également créé une stack supplémentaire qui stockera les noms de titres de la barre d’action. Chaque fois que j’ajoute un nouveau fragment au backstack, j’ajoute le nom du titre correspondant à ma stack créée. Sur le côté opposé, chaque fois que j’appuie sur le bouton de retour, on appelle BackStackChanged () et je place le nom du dernier titre de ma stack et je mets le titre sur le nom dérivé de la méthode peek () de la stack.

Exemple:

Disons que notre backstack Android est vide:

Appuyez sur Choix 1 dans le tiroir de navigation: onBackStachChanged () est appelé et le fragment 1 est ajouté à l’arrière-plan Android, backStackEntryCount est défini sur 1 et Frag1 est poussé sur ma stack et la taille de mFragPositionTitleDisplayed devient 1.

Appuyez sur Choix 2 dans le tiroir de navigation: onBackStachChanged () est appelé et le fragment 2 est ajouté à l’arrière-plan Android.

Nous avons maintenant 2 éléments à la fois dans la stack android et dans ma stack. Lorsque vous appuyez sur le bouton onBackStackChanged () est appelé et la valeur de backStackEntryCount est 1. Le code entre la partie if et la dernière entrée de ma stack. Donc, le backstack Android n’a qu’un fragment – “Fragment 1” et ma stack n’a qu’un seul titre – “Frag1”. Maintenant, je regarde juste () le titre de ma stack et place la barre d’action sur ce titre.

Rappelez-vous: pour définir le titre de la chauve-souris d’action, utilisez peek () et non pop (), sinon votre application se bloquera lorsque vous ouvrirez plus de 2 fragments et tenterez de revenir en arrière en appuyant sur le bouton.

Vous pouvez résoudre avec onKeyDown! J’ai un bool mainisopen = true <- MainFragment est visible autre Fragment mainisopen = false

et voici mon code:

 public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && mainisopen == false) { mainisopen = true; HomeFrag fragment = new HomeFrag(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.fragmet_cont, fragment); fragmentTransaction.commit(); navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.getMenu().findItem(R.id.nav_home).setChecked(true); navigationView.setNavigationItemSelectedListener(this); this.setTitle("Digi - Home"); //Here set the Title back return true; } else { if (keyCode == KeyEvent.KEYCODE_BACK && mainisopen == true) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Wollen sie die App schliessen!"); builder.setCancelable(true); builder.setPositiveButton("Ja!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { System.exit(1); } }); builder.setNegativeButton("Nein!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Toast.makeText(getApplicationContext(), "Applikation wird fortgesetzt", Toast.LENGTH_SHORT).show(); } }); AlertDialog dialog = builder.create(); dialog.show(); return true; } return super.onKeyDown(keyCode, event); } } 

Pour mettre à jour le titre de la barre d’action sur l’appui arrière. Simplement mettre

getActivity.setTitle (“title”)

à l’intérieur de la méthode onCreateView.