getSupportActionBar from inside of Fragment ActionBarCompat

冷暖自知 提交于 2019-11-27 05:05:18

问题


I'm starting a new project that uses the AppCompat/ActionBarCompat in v7 support library. I'm trying to figure out how to use the getSupportActionBar from within a fragment. My activity that hosts the fragment extends ActionBarActivity, but I don't see a similar support class for Fragments.

From within my fragment

    public class CrimeFragment extends Fragment {
          //...

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

          //...
    }

The google page for using it (http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html) says there should be no changes for the v4 fragment. Do I need to cast all my getActivity() calls to an ActionBarActivity? That seems like poor design.


回答1:


After Fragment.onActivityCreated(...) you'll have a valid activity accessible through getActivity().

You'll need to cast it to an ActionBarActivity then make the call to getSupportActionBar().

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

You do need the cast. It's not poor design, it's backwards compatibility.




回答2:


While this question has an accepted answer already, I must point out that it isn't totally correct: calling getSupportActionBar() from Fragment.onAttach() will cause a NullPointerException when the activity is rotated.

Short answer:

Use ((ActionBarActivity)getActivity()).getSupportActionBar() in onActivityCreated() (or any point afterwards in its lifecycle) instead of onAttach().

Long answer:

The reason is that if an ActionBarActivity is recreated after a rotation, it will restore all Fragments before actually creating the ActionBar object.

Source code for ActionBarActivity in the support-v7 library:

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate() creates the mImpl object depending on the Android version.
  • super.onCreate() is FragmentActivity.onCreate(), which restores any previous fragments after a rotation (FragmentManagerImpl.dispatchCreate(), &c).
  • mImpl.onCreate(savedInstanceState) is ActionBarActivityDelegate.onCreate(), which reads the mHasActionBar variable from the window style.
  • Before mHasActionBar is true, getSupportActionBar() will always return null.

Source for 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;
}



回答3:


If someone uses com.android.support:appcompat-v7: and AppCompatActivity as activity then this will work

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



回答4:


in your fragment.xml add Toolbar Tag from support library

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

Now how we can control it from MyFragment class? let's see

inside onCreateView function add the following

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

and if you want to add items to the toolbar within MyFragment you must add this line inside onCreateView function

        setHasOptionsMenu(true);

this line is important, if you forget it, android will not populate your menu Items.

assume we identify them in menu/fragment_menu.xml

after that override the following functions

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

hope this helps




回答5:


As an updated answer for Pierre-Antoine LaFayette's answer

ActionBarActivity is deprecated; use AppCompatActivity instead

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



回答6:


For those using kotlin,

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


来源:https://stackoverflow.com/questions/18320713/getsupportactionbar-from-inside-of-fragment-actionbarcompat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!