74 votes

Gestion du titre de la barre d'action avec la pile arrière du fragment ?

J'ai un Activity où je charge dans un ListFragment et, en cliquant, on descend d'un niveau et on obtient un nouveau type d'informations. ListFragment est affichée, remplaçant celle d'origine (en utilisant l'option showFragment méthode ci-dessous). Celle-ci est placée sur la pile arrière.

Au début, l'activité affiche le titre par défaut dans la barre d'action (c'est-à-dire qu'il est défini automatiquement sur la base de l'application android:label ).

Lors de l'affichage de la liste du niveau suivant de la hiérarchie, le nom de l'élément sur lequel on a cliqué doit devenir le titre de la barre d'action.

Cependant, en appuyant sur Back J'aimerais que le titre original par défaut soit restauré. Ce n'est pas quelque chose FragmentTransaction connaît, donc le titre n'est pas rétabli.

J'ai vaguement lu quelque chose sur 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 procéder ? Est-il possible de le faire sans avoir recours à un tas de code passe-partout et sans devoir 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();
}

5voto

Gnzlt Points 613

J'utilise une solution similaire pour Approche de Lee mais en remplaçant onBackStackChanged() à la place.

J'ai d'abord défini le nom du fragment lors de l'ajout de la transaction à la pile arrière.

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

Ensuite, je remplace le onBackStackChanged() et j'appelle setTitle() avec le nom de la dernière entrée du backstack.

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

    setTitle(lastBackStackEntry.getName());
}

4voto

Utilisez la méthode des fragments :

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

Il est appelé à chaque apparition de Fragment, mais onResume ne l'est pas.

1voto

Abhishek Points 29

La meilleure approche consiste à utiliser la méthode onBackStackChanged() de l'interface OnBackStackChangedListener fournie par Android.

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 j'expliquerai le fonctionnement.

    private int mPreviousBackStackCount = 0;
    private String[] title_name = {"Frag1","Frag2","Frag3","Frag4"};
    Stack<String> 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.string.app_name);
        else if (backStackEntryCount > 0) {
            getSupportActionBar().setTitle(mFragPositionTitleDisplayed.peek());
        }
        mPreviousBackStackCount--;
    }
    else{
        mFragPositionTitleDisplayed.push(title_name[position]);
        mPreviousBackStackCount++;
    }

}   

Dans le code présenté, nous avons la méthode displayFragment(). Ici, j'affiche le fragment sur la base de l'option choisie dans le tiroir de navigation. La variable position correspond à la position de l'élément cliqué dans la ListView ou la RecyclerView dans le tiroir de navigation. Je définis le titre de la barre d'action en conséquence avec getSupportActionBar.setTitle(title), où le titre enregistre le nom du titre approprié.

Chaque fois que l'on clique sur un élément du tiroir de navigation, un fragment est affiché en fonction de l'élément cliqué par l'utilisateur. Mais du côté du back-end, ce fragment est ajouté à la pile arrière et la méthode onBackStachChanged() est activée. Ce que j'ai fait, c'est que j'ai créé une variable mPreviousBackStackCount et l'ai initialisée à 0. J'ai également créé une pile supplémentaire qui stockera les noms des titres des barres d'action. Chaque fois que j'ajoute un nouveau fragment à la pile arrière, j'ajoute le nom du titre correspondant à la pile créée. De l'autre côté, chaque fois que j'appuie sur le bouton "back", onBackStackChanged() est appelé et je sors le dernier nom de titre de ma pile et je fixe le titre au nom dérivé par la méthode peek() de la pile.

Exemple :

Disons que notre backstack Android est vide :

Appuyez sur le choix 1 du tiroir nav : onBackStachChanged() est appelé et le Fragment 1 est ajouté à la pile arrière d'Android, backStackEntryCount est fixé à 1 et le Frag1 est poussé vers ma pile et la taille de mFragPositionTitleDisplayed devient 1.

Appuyez sur le choix 2 du tiroir nav : onBackStachChanged() est appelé et le Fragment 2 est ajouté à la pile arrière d'Android, backStackEntryCount est fixé à 2 et le Frag2 est poussé vers ma pile et la taille de mFragPositionTitleDisplayed devient 2.

Maintenant nous avons 2 éléments à la fois dans la pile Android et dans ma pile. Lorsque vous appuyez sur le bouton retour onBackStackChanged() est appelé et la valeur de backStackEntryCount est de 1. Le code entre dans la partie if et sort la dernière entrée de ma pile. Ainsi, la pile arrière d'Android ne contient qu'un seul fragment - "Fragment 1" et ma pile ne contient qu'un seul titre - "Frag1". Maintenant, j'ai juste à regarder() le titre de ma pile et à définir la barre d'action sur ce titre.

Rappelez-vous : Pour définir le titre du batteur d'action, utilisez peek() et non pop(), sinon votre application se plantera si vous ouvrez plus de 2 fragments et essayez de revenir en arrière en appuyant sur le bouton retour.

1voto

BitDEVil2K16 Points 139

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

}

0voto

mDonmez Points 273

Comme décrit aquí ma solution est d'ajouter ce code à la méthode onCreate de MainActivity() : et de changer le titre de la barre d'action

FragmentManager fragmentManager=getSupportFragmentManager();
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
    @Override
    public void onBackStackChanged() {
        Fragment currentFragment = fragmentManager.findFragmentById(R.id.My_Container_1_ID);
        currentFragment.onResume();
    }
});

et changer le titre de la barre d'action dans la méthode onResume() du fragment

@Override
public void onResume() {
    super.onResume();
    AppCompatActivity activity = (AppCompatActivity) getActivity();
    ActionBar actionBar = activity.getSupportActionBar();
    if(actionBar!=null) {
        actionBar.setTitle("Fragment Title");
        actionBar.setSubtitle("Subtitle");
    }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X