web-dev-qa-db-fra.com

getSupportActionBar depuis l'intérieur de Fragment ActionBarCompat

Je commence un nouveau projet qui utilise la bibliothèque de support AppCompat/ActionBarCompat dans v7. J'essaie de comprendre comment utiliser la variable getSupportActionBar à partir d'un fragment. Mon activité qui héberge le fragment s'étend ActionBarActivity, mais je ne vois pas de classe de support similaire pour Fragments.

De l'intérieur de mon fragment

    public class CrimeFragment extends Fragment {
          //...

          getActivity().getSupportActionBar().setSubtitle(R.string.subtitle); // getSupportActionBar is not defined in the v4 version of Fragment

          //...
    }

La page google pour l'utiliser ( http://Android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html ) indique qu'il ne devrait y avoir aucune modification pour le v4 fragment. Dois-je convertir tous mes appels getActivity() en ActionBarActivity? Cela semble être une mauvaise conception.

92
Paul

Après Fragment.onActivityCreated (...) vous aurez une activité valide accessible via getActivity (). 

Vous devrez le convertir en ActionBarActivity, puis appeler getSupportActionBar ().

((AppCompatActivity)getActivity()).getSupportActionBar().setSubtitle(R.string.subtitle);

Vous avez besoin du casting. Ce n'est pas une mauvaise conception, c'est une compatibilité ascendante.

259

Bien que cette question ait déjà une réponse acceptée, je dois souligner que ce n’est pas tout à fait correct: appeler getSupportActionBar() à partir de Fragment.onAttach() provoquera un NullPointerException lorsqu’une rotation de l’activité est effectuée.

Réponse courte:  

Utilisez ((ActionBarActivity)getActivity()).getSupportActionBar() dansonActivityCreated()(ou tout autre point suivant dans son cycle de vie) au lieu de onAttach().

Longue réponse:

La raison en est que si un ActionBarActivity est recréé après une rotation, il restaure tous les fragments avant créant en fait l'objet ActionBar.

Code source pour ActionBarActivity dans la bibliothèque support-v7:

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate() crée l'objet mImpl en fonction de la version Android.
  • super.onCreate() est FragmentActivity.onCreate(), ce qui restaure les fragments précédents après une rotation (FragmentManagerImpl.dispatchCreate(), & c).
  • mImpl.onCreate(savedInstanceState) est ActionBarActivityDelegate.onCreate(), qui lit la variable mHasActionBar à partir du style de fenêtre.
  • Avant que mHasActionBar soit vrai, getSupportActionBar() renvoie toujours null.

Source pour ActionBarActivityDelegate.getSupportActionBar():

final ActionBar getSupportActionBar() {
    // The Action Bar should be lazily created as mHasActionBar or mOverlayActionBar
    // could change after onCreate
    if (mHasActionBar || mOverlayActionBar) {
        if (mActionBar == null) {
            ... creates the action bar ...
        }
    } else {
        // If we're not set to have a Action Bar, null it just in case it's been set
        mActionBar = null;
    }
    return mActionBar;
}
35
matiash

Si quelqu'un utilise com.Android.support:appcompat-v7: et AppCompatActivity comme activité, cela fonctionnera

((AppCompatActivity)getActivity()).getSupportActionBar().setSubtitle(R.string.subtitle);
29
Amir

dans votre fragment.xml add Toolbar Tag de la bibliothèque de support

 <Android.support.v7.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

Maintenant, comment pouvons-nous le contrôler depuis la classe MyFragment? Voyons voir

dans la fonction onCreateView, ajoutez ce qui suit

mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);

//add this line if you want to provide Up Navigation but don't forget to to 
//identify parent activity in manifest file
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);

et si vous voulez ajouter items à la barre d’outils dans MyFragment vous must ajouter cette ligne dans la fonction onCreateView 

        setHasOptionsMenu(true);

cette ligne est importante, si vous l'oubliez, Android ne peuplera pas vos éléments de menu. 

supposons que nous les identifions dans menu/fragment_menu.xml

après cela remplacer les fonctions suivantes 

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.fragment_menu, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    switch (id) {
        case R.id.action_1:
            // do stuff
            return true;

        case R.id.action_2:
            // do more stuff
            return true;
    }

    return false;
}

j'espère que cela t'aides

4
Basheer AL-MOMANI

Réponse actualisée de la réponse de Pierre-Antoine LaFayette

ActionBarActivity est obsolète; utilisez AppCompatActivity à la place

((AppCompatActivity)getActivity()).getSupportActionBar();
3
Dasser Basyouni

Pour ceux qui utilisent kotlin,

(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)
0
GzDevs