getSupportActionBar dall'interno di Fragment ActionBarCompat


102

Sto iniziando un nuovo progetto che utilizza la libreria AppCompat/ActionBarCompatin v7support. Sto cercando di capire come utilizzare getSupportActionBardall'interno di un frammento. La mia attività che ospita il frammento si estende ActionBarActivity, ma non vedo una classe di supporto simile per i frammenti.

Dall'interno del mio frammento

    public class CrimeFragment extends Fragment {
          //...

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

          //...
    }

La pagina google per utilizzarlo ( http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html ) dice che non dovrebbero esserci modifiche per il v4frammento. Devo trasmettere tutte le mie getActivity()chiamate a un ActionBarActivity? Sembra un design scadente.

Risposte:


287

Dopo Fragment.onActivityCreated (...) avrai un'attività valida accessibile tramite getActivity ().

Dovrai trasmetterlo a un ActionBarActivity, quindi effettuare la chiamata a getSupportActionBar ().

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

Hai bisogno del cast. Non è un design scadente, è retrocompatibile.


3
Grazie. Speravo che questa non fosse la risposta. Speravo forse che getActionBar () restituisse una ActionBar v7 a cui avrei eseguito il cast se avessi avuto bisogno della funzionalità extra. Ora i miei frammenti devono essere consapevoli del tipo di attività in cui sono ospitati.
Paul

No, perché getActionBar () è un'API di attività che non esiste nelle versioni precedenti dell'SDK (pre-honeycomb). Questo è il motivo per cui abbiamo bisogno di classi di supporto che rispecchino la funzionalità delle classi e delle API nuove e migliorate negli SDK più recenti.
Pierre-Antoine LaFayette

@ Pierre-AntoineLaFayette Perché è necessario farlo in onAttach ()? Non sarebbe meglio in onActivityCreated ()?
IgorGanapolsky

Sì, poiché la prima chiamata a getSupportActionBar () inizializzerà ActionBar cercando le viste nell'attività, è probabilmente meglio che questa chiamata venga eseguita in onActivityCreated (). Stavo solo cercando di indicare che devi aspettare che il frammento abbia un'attività. Aggiornerò la risposta.
Pierre-Antoine LaFayette

2
Usa AppCompatActivity invece di ActionBarActivity
Aparajita Sinha

37

Sebbene questa domanda abbia già una risposta accettata, devo sottolineare che non è del tutto corretta: la chiamata getSupportActionBar()da Fragment.onAttach()causerà un NullPointerExceptionquando l'attività viene ruotata.

Risposta breve:

Utilizzare ((ActionBarActivity)getActivity()).getSupportActionBar()in onActivityCreated()(o in qualsiasi punto successivo del suo ciclo di vita) invece di onAttach().

Risposta lunga:

Il motivo è che se ActionBarActivityviene ricreato dopo una rotazione, ripristinerà tutti i frammenti prima di creare effettivamente l' ActionBaroggetto.

Il codice sorgente per ActionBarActivityla support-v7libreria:

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate()crea l' mImploggetto a seconda della versione di Android.
  • super.onCreate()è FragmentActivity.onCreate(), che ripristina eventuali frammenti precedenti dopo una rotazione ( FragmentManagerImpl.dispatchCreate(), ecc).
  • mImpl.onCreate(savedInstanceState)è ActionBarActivityDelegate.onCreate(), che legge la mHasActionBarvariabile dallo stile della finestra.
  • Prima mHasActionBarè vero, getSupportActionBar()tornerà sempre null.

Fonte per 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;
}

2
ActionBarActivityè deprecato. Usa AppCompatActivityinvece
Saman Sattari

29

Se qualcuno usa com.android.support:appcompat-v7: e AppCompatActivity come attività, allora funzionerà

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

5

nel tuo tag fragment.xmlaggiungi Toolbardalla libreria di supporto

 <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" />

Ora come possiamo controllarlo dalla MyFragmentclasse? vediamo

all'interno della onCreateViewfunzione aggiungere quanto segue

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

e se vuoi aggiungere itemsalla barra degli strumenti dentro di MyFragment te mustaggiungi questa linea all'interno della onCreateViewfunzione

        setHasOptionsMenu(true);

questa riga è importante, se la dimentichi, Android non popolerà le voci del menu.

supponiamo di identificarli in menu/fragment_menu.xml

dopodiché sovrascrivono le seguenti funzioni

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

spero che questo ti aiuti


5

Come una risposta aggiornata per la risposta di Pierre-Antoine LaFayette

ActionBarActivity è deprecato; usa AppCompatActivityinvece

((AppCompatActivity)getActivity()).getSupportActionBar();

3

Per coloro che usano kotlin,

(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.