wake-up-neo.com

getSupportActionBar aus Fragment ActionBarCompat heraus

Ich starte ein neues Projekt, das die AppCompat/ActionBarCompat in der v7-Unterstützungsbibliothek verwendet. Ich versuche herauszufinden, wie man die getSupportActionBar innerhalb eines Fragments verwendet. Meine Aktivität, die das Fragment hostet, erweitert ActionBarActivity, aber ich sehe keine ähnliche Unterstützungsklasse für Fragmente.

Aus meinem Fragment heraus

    public class CrimeFragment extends Fragment {
          //...

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

          //...
    }

Auf der Google-Seite ( http://Android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html ) wird angegeben, dass für den v4 keine Änderungen vorgenommen werden sollten. Fragment. Muss ich alle meine getActivity()-Aufrufe in eine ActionBarActivity umsetzen? Das scheint schlechtes Design zu sein.

92
Paul

Nach Fragment.onActivityCreated (...) haben Sie eine gültige Aktivität, die über getActivity () zugänglich ist. 

Sie müssen es in ActionBarActivity umwandeln und dann getSupportActionBar () aufrufen.

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

Du brauchst die Besetzung. Es ist kein schlechtes Design, es ist Rückwärtskompatibilität.

Obwohl diese Frage bereits akzeptiert wurde, muss ich darauf hinweisen, dass sie nicht völlig korrekt ist: Wenn Sie getSupportActionBar() von Fragment.onAttach() aufrufen, wird eine NullPointerException ausgelöst, wenn die Aktivität gedreht wird.

Kurze Antwort:  

Verwenden Sie ((ActionBarActivity)getActivity()).getSupportActionBar() inonActivityCreated()(oder einen beliebigen Punkt danach in seinem Lebenszyklus) anstelle von onAttach().

Lange Antwort:

Der Grund ist, dass wenn eine ActionBarActivity nach einer Drehung neu erstellt wird, alle Fragmente vor wiederhergestellt werden, wodurch das ActionBar-Objekt tatsächlich erstellt wird.

Quellcode für ActionBarActivity in der support-v7-Bibliothek:

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate() erstellt das mImpl-Objekt abhängig von der Android-Version.
  • super.onCreate() ist FragmentActivity.onCreate(), wodurch nach einer Rotation alle vorherigen Fragmente wiederhergestellt werden (FragmentManagerImpl.dispatchCreate(), & c).
  • mImpl.onCreate(savedInstanceState) ist ActionBarActivityDelegate.onCreate(), die die Variable mHasActionBar aus dem Fensterstil liest.
  • Bevor mHasActionBar wahr ist, gibt getSupportActionBar() immer null zurück.

Quelle für 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

Wenn jemand com.Android.support:appcompat-v7: und AppCompatActivity als Aktivität verwendet, funktioniert dies

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

in Ihrem fragment.xml add Toolbar Tag aus der Support-Bibliothek

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

Wie können wir es nun von der MyFragment-Klasse aus steuern? Mal schauen

in der Funktion onCreateView fügen Sie Folgendes hinzu

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

und wenn Sie items zur Symbolleiste in MyFragment .__ hinzufügen möchten, fügen Sie must diese Zeile in onCreateView-Funktion hinzu 

        setHasOptionsMenu(true);

diese Zeile ist wichtig. Wenn Sie es vergessen, füllt Android Ihre Menüelemente nicht auf. 

angenommen, wir identifizieren sie in menu/fragment_menu.xml

danach überschreiben Sie die folgenden Funktionen 

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

hoffe das hilft

4

Als aktualisierte Antwort auf die Antwort von Pierre-Antoine LaFayette

ActionBarActivity ist veraltet. Verwenden Sie stattdessen AppCompatActivity

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

Für diejenigen, die Kotlin verwenden,

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