82

Sto avviando un nuovo progetto che utilizza lo AppCompat/ActionBarCompat nella libreria di supporto v7. Sto cercando di capire come utilizzare getSupportActionBar all'interno di un frammento. La mia attività che ospita il frammento si estende a ActionBarActivity, ma non vedo una classe di supporto simile per Fragments.getSupportActionBar dall'interno di Fragment ActionBarCompat

da dentro il 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 di Google per il suo utilizzo (http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html) dice non ci dovrebbero essere cambiamenti per il frammento v4. Devo trasmettere tutte le mie chiamate getActivity() a un ActionBarActivity? Sembra un design scadente.

+0

Può spiegare come si risolve questo problema? –

risposta

229

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

Avrete bisogno di lanciarlo su ActionBarActivity quindi effettuare la chiamata a getSupportActionBar().

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

È necessario il cast. Non è un design scadente, è retrocompatibile.

+3

Grazie. Speravo che questa non sarebbe stata la risposta. Speravo forse che getActionBar() restituisse un ActionBar v7 su cui avrei eseguito il cast se avessi bisogno della funzionalità extra. Ora i miei frammenti devono essere a conoscenza del tipo di attività in cui sono ospitati. – Paul

+0

No, perché getActionBar() è un'API Activity 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 API nuove e migliorate negli SDK più recenti. –

+0

@ Pierre-AntoineLaFayette Perché questo deve essere fatto in onAttach()? Non sarebbe meglio in onActivityCreated()? –

33

Mentre questa domanda ha già una risposta accettata, devo sottolineare che non è del tutto corretto: chiamare getSupportActionBar() da Fragment.onAttach() causerà un NullPointerException quando l'attività viene ruotata.

Risposta breve:

Usa ((ActionBarActivity)getActivity()).getSupportActionBar() in onActivityCreated() (o qualsiasi punto in seguito nel suo ciclo di vita), invece di onAttach().

Risposta lunga:

La ragione è che se un ActionBarActivity viene ricreato dopo una rotazione, si ripristinerà tutti i frammenti prima creare effettivamente l'oggetto ActionBar.

Il codice sorgente per ActionBarActivity nella biblioteca support-v7:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    mImpl = ActionBarActivityDelegate.createDelegate(this); 
    super.onCreate(savedInstanceState); 
    mImpl.onCreate(savedInstanceState); 
} 
  • ActionBarActivityDelegate.createDelegate() crea l'oggetto mImpl a seconda della versione di Android.
  • super.onCreate() è FragmentActivity.onCreate(), che ripristina i frammenti precedenti dopo una rotazione (FragmentManagerImpl.dispatchCreate(), & c).
  • mImpl.onCreate(savedInstanceState) è ActionBarActivityDelegate.onCreate(), che legge la variabile mHasActionBar dallo stile della finestra.
  • Prima che mHasActionBar sia vero, getSupportActionBar() restituirà 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; 
} 
25

Se qualcuno utilizza com.android.support:appcompat-v7: e AppCompatActivity l'attività allora questo funzionerà

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

nel vostro fragment.xml aggiungere Toolbar Tag dalla 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 classe MyFragment? vediamo

all'interno onCreateView funzione di aggiungere il seguente

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 si desidera aggiungere items alla barra degli strumenti all'interno MyFragment si must aggiungere questa linea all'interno onCreateView funzione

 setHasOptionsMenu(true); 

questa linea è importante, se lo dimentichi, Android non popolerà le voci del tuo menu.

assumere noi li identifichiamo in menu/fragment_menu.xml

dopo che ignorare 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; 
} 

speranza che questo aiuta

0

Come risposta aggiornata la risposta di Pierre-Antoine LaFayette

ActionBarActivity è deprecato; utilizzare AppCompatActivity invece

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