82

Zaczynam nowy projekt, który używa biblioteki pomocniczej AppCompat/ActionBarCompat w v7. Próbuję dowiedzieć się, jak korzystać z getSupportActionBar z fragmentu. Moja aktywność obsługująca fragment rozszerza się o ActionBarActivity, ale nie widzę podobnej klasy wsparcia dla Fragmentów.getSupportActionBar od środka Fragment ActionBarCompat

Od wewnątrz mojego fragmentu

public class CrimeFragment extends Fragment { 
      //... 

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

      //... 
    } 

stronie Google za korzystanie z niego (http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html) mówi, że nie powinno być żadnych zmian dla v4 fragmentu. Czy muszę obsłużyć wszystkie moje połączenia getActivity() z ActionBarActivity? To wygląda na kiepski projekt.

+0

Czy możesz wyjaśnić, jak rozwiązać ten problem? –

Odpowiedz

229

Po Fragment.onActivityCreated (...) będziesz mieć prawidłowe działanie dostępne przez getActivity().

Musisz rzucić go do ActionBarActivity, a następnie wywołać metodę getSupportActionBar().

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

Potrzebujesz obsady. To nie jest kiepski projekt, to kompatybilność wsteczna.

+3

Dzięki. Miałem nadzieję, że to nie będzie odpowiedź. Miałem nadzieję, że może getActionBar() zwróci VB ActionBar, który bym rzucił, gdybym potrzebował dodatkowej funkcjonalności. Teraz moje Fragmenty muszą być świadome rodzaju Aktywności, w której się znajdują. – Paul

+0

Nie, nie, ponieważ getActionBar() to API działania, które nie istnieje w starszych wersjach SDK (pre-honeycomb). Dlatego potrzebujemy klas wsparcia, które odzwierciedlają funkcjonalność nowych i ulepszonych klas i interfejsów API w nowszych pakietach SDK. –

+0

@ Pierre-AntoineLaFayette Dlaczego należy to zrobić w onAttach()? Czy nie byłoby lepiej w onActivityCreated()? –

33

Podczas gdy to pytanie ma już zaakceptowaną odpowiedź, muszę zaznaczyć, że nie jest to całkowicie poprawne: wywołanie getSupportActionBar() z Fragment.onAttach() spowoduje NullPointerException, gdy aktywność zostanie obrócona.

Krótka odpowiedź:

Zastosowanie ((ActionBarActivity)getActivity()).getSupportActionBar() w onActivityCreated() (lub dowolnym punkcie później w jego cyklu życia) zamiast onAttach().

Długa odpowiedź:

Powodem jest to, że jeśli ActionBarActivity jest odtwarzany po obrocie, będzie przywrócić wszystkie fragmenty przed faktycznie tworzenia obiektu ActionBar.

Kod źródłowy ActionBarActivity w bibliotece support-v7:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    mImpl = ActionBarActivityDelegate.createDelegate(this); 
    super.onCreate(savedInstanceState); 
    mImpl.onCreate(savedInstanceState); 
} 
  • ActionBarActivityDelegate.createDelegate() tworzy obiekt mImpl zależności od wersji Androida.
  • super.onCreate() to FragmentActivity.onCreate(), który przywraca wszystkie poprzednie fragmenty po obrocie (FragmentManagerImpl.dispatchCreate(), & c).
  • mImpl.onCreate(savedInstanceState) to ActionBarActivityDelegate.onCreate(), który odczytuje zmienną mHasActionBar ze stylu okna.
  • Przed mHasActionBar jest zawsze prawdziwe, getSupportActionBar() zawsze zwróci null.

źródło 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

Jeśli ktoś używa com.android.support:appcompat-v7 a AppCompatActivity jako działalność, wówczas będzie to działać

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

w swojej fragment.xml dodać Toolbar Znacznik z biblioteki pomocniczej

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

Jak możemy to kontrolować z klasy MyFragment? Zobaczmy

wewnątrz onCreateView funkcja dodaj następującą

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

i jeśli chcesz dodać items do paska narzędzi w ciągu MyFragment must dodać tę linię wewnątrz onCreateView funkcji

 setHasOptionsMenu(true); 

ta linia jest ważne, jeśli zapomnisz, Android nie zapełni pozycji menu.

zakładać utożsamiamy je menu/fragment_menu.xml

potem zastępują następujące funkcje

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

nadzieję, że to pomaga

0

Jak zaktualizowaną odpowiedź na odpowiedź Pierre-Antoine Lafayette

ActionBarActivity jest przestarzałe; użyj AppCompatActivity zamiast:

((AppCompatActivity)getActivity()).getSupportActionBar(); 
Powiązane problemy