Fragment ActionBarCompat内からのgetSupportActionBar


102

私が使用して新しいプロジェクトを始めているAppCompat/ActionBarCompatv7サポートライブラリを。getSupportActionBarフラグメント内からの使用方法を理解しようとしています。フラグメントをホストする私のアクティビティは拡張されますが、フラグメントActionBarActivityの同様のサポートクラスが表示されません。

私の断片の中から

    public class CrimeFragment extends Fragment {
          //...

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

          //...
    }

それを使用するためのGoogleページ(http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html)は、v4フラグメントに変更はないはずであると述べています。すべてのgetActivity()呼び出しをにキャストする必要がありActionBarActivityますか?それは貧弱なデザインのようです。

回答:


287

Fragment.onActivityCreated(...)の後に、getActivity()を介してアクセスできる有効なアクティビティがあります。

これをActionBarActivityにキャストしてから、getSupportActionBar()を呼び出す必要があります。

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

キャストが必要です。これは貧弱な設計ではなく、下位互換性です。


3
ありがとう。これが答えにならないことを願っていました。getActionBar()がv7 ActionBarを返し、追加の機能が必要な場合にキャストできることを期待していました。今、私のフラグメントは、それらがホストされている活動の種類を認識する必要があります。
ポール・

いいえ、そうではありません。getActionBar()は、古いバージョンのSDK(pre-honeycomb)には存在しないActivity APIだからです。このため、最近のSDKの新しく改善されたクラスとAPIの機能を反映するサポートクラスが必要です。
Pierre-Antoine LaFayette 2013

@ Pierre-AntoineLaFayetteなぜこれをonAttach()で行わなければならないのですか?onActivityCreated()のほうが良いのではないでしょうか?
IgorGanapolsky 2014

はい、getSupportActionBar()への最初の呼び出しはアクティビティのビューを検索することでActionBarを初期化するため、この呼び出しはonActivityCreated()で実行する方が良いでしょう。私は、フラグメントにアクティビティが発生するまで待機する必要があることを示しようとしています。答えを更新します。
ピエールアントワーヌラファイエット2014

2
ActionBarActivityの代わりにAppCompatActivityを使用する
Aparajita Sinha 2017

37

この質問はすでに受け入れ答えを持っていますが、私はそれが完全に正しくないことを指摘しなければなりません:呼び出しgetSupportActionBar()からFragment.onAttach()意志の原因ANullPointerExceptionアクティビティを回転させたとき。

短い答え:

の代わり((ActionBarActivity)getActivity()).getSupportActionBar()onActivityCreated()(またはその後のライフサイクルの任意の時点)を使用しonAttach()ます。

長い答え:

その理由はActionBarActivity、ローテーション後にを再作成すると、実際に作成するにすべてのフラグメントを復元するためです。ActionBarオブジェクトをです。

ライブラリActionBarActivity内のソースコードsupport-v7

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate() 作成します mImplAndroidのバージョンに応じオブジェクトをます。
  • super.onCreate()is FragmentActivity.onCreate()、ローテーション後に以前のフラグメントを復元します(FragmentManagerImpl.dispatchCreate()、&​​c)の。
  • mImpl.onCreate(savedInstanceState)ActionBarActivityDelegate.onCreate()mHasActionBarウィンドウスタイルから変数ます。
  • before mHasActionBarがtrueの場合、getSupportActionBar()常にが返されnullます。

ソース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廃止予定です。AppCompatActivity代わりに使用
Saman Sattari、

29

誰かがcom.android.support:appcompat-v7:とAppCompatActivityをアクティビティとして使用している場合、これは機能します

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

5

あなたの中にfragment.xml追加のToolbarサポートライブラリからのタグ

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

では、MyFragmentクラスからそれをどのように制御できるでしょうか。どれどれ

onCreateView関数内に以下を追加

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

itemsツールバーに追加したい場合は、関数内にこの行MyFragmentmust追加しonCreateViewます

        setHasOptionsMenu(true);

この行は重要です。忘れると、Androidはメニュー項目を表示しません。

私たちがそれらを特定すると仮定します menu/fragment_menu.xml

その後、次の関数をオーバーライドします

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

お役に立てれば


5

Pierre-Antoine LaFayetteの回答の更新された回答として

ActionBarActivityは非推奨です。AppCompatActivity代わりに使用

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

3

コトリンを使っている人は

(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.