简体   繁体   中英

Switching fragments on Navigation Drawer item click

I am using the navigation drawer in my app and implemented the logic for switching the fragments inside the NavigationDrawerFragment class. I have read recently that fragment switching can happen only from the hosting activity.

There is an interface called from the NavigationDrawerFragment to notify the MainActivity of the selected position in the Navigation Drawer listview.

public static interface NavigationDrawerCallbacks {
    /**
     * Called when an item in the navigation drawer is selected.
     */
    void onNavigationDrawerItemSelected(int position);
} 

Where I get confused is that there is a Static fragment inside the MainActivity that is called with the the position supplied from the interface in NavigationDrawerFragment.

@Override
public void onNavigationDrawerItemSelected(int position) {

    FragmentManager fragmentManager = getFragmentManager(); 
    fragmentManager
            .beginTransaction()
            .replace(R.id.container,
                    PlaceholderFragment.newInstance(position)).commit();

}

The PlaceHolderFragment class looks like this:

public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    /**
     * Returns a new instance of this fragment for the given section number.
     */
    public static Fragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();

        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container,
                false);
        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((MCMainActivity) activity).onSectionAttached(getArguments()
                .getInt(ARG_SECTION_NUMBER));
    }
}

Currently my fragment transactions happen like this:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    mDrawerListView = (ListView) inflater.inflate(
            R.layout.fragment_navigation_drawer, container, false);
    mDrawerListView
            .setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                        int position, long id) {
                    selectItem(position);
                    Fragment fragment;
                    FragmentManager fManager = getFragmentManager();

                    int count = fManager.getBackStackEntryCount();
                    for (int i = 0; i < count; ++i) {

                        fManager.popBackStackImmediate();
                        Log.e("NavFrag", "Popped frag" + i);
                    }
                    FragmentTransaction fTransaction = fManager
                            .beginTransaction();
                    switch (position) {
                    case 0:
                        fragment = new MCTrackFragment();
                        fTransaction.replace(R.id.container, fragment)

                                .commit();
                        break;
                    case 1:
                        fragment = new MCPlaylistFragment();
                        fTransaction.replace(R.id.container, fragment)
                                .commit();
                        break;
                    case 2:
                        fragment = new MCOfflineSongs();
                        fTransaction.replace(R.id.container, fragment)
                                .commit();
                        break;
                    case 3:
                        fragment = new MCOwnFeed();
                        fTransaction.replace(R.id.container, fragment)
                                .commit();
                        break;
                    case 4:
                        fragment = new MCCategories();
                        fTransaction.replace(R.id.container, fragment)
                                .commit();
                        break;
                    }
                }
            });
    mDrawerListView.setAdapter(new ArrayAdapter<String>(getActionBar()
            .getThemedContext(),
            android.R.layout.simple_list_item_activated_1,
            android.R.id.text1, new String[] {
                    getString(R.string.title_section1),
                    getString(R.string.title_section2),
                    getString(R.string.title_section3),
                    getString(R.string.title_section4),
                    getString(R.string.title_section5) }));
    mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
    return mDrawerListView;
}

The placeholder fragment is auto generated when we create a project with navigationdrawer .

What is the placeholder fragment for?

What should I do to make the fragment transactions happen inside the Activity that hosts these fragments?

I tried adding the fragment transactions inside the interface implementation but its not working.

Help is appreciated, thanks in advance

It is right that we need to ALWAYS switch fragments from an activity so we need to provide a callback from the navigation drawer fragment to the activity that is going to host the new fragment to be displayed. Inside the activity the code for switching the fragments is as follows:

@Override
public void onNavigationDrawerItemSelected(int position) {

    Fragment fragment;
    FragmentManager fManager = getFragmentManager();
    Bundle args = new Bundle();
    args.putInt(MCConstants.ARG_SECTION_NUMBER, position);
    clearAllBackStack();
    FragmentTransaction fTransaction = fManager.beginTransaction();
    if (MCMediaPlayerService.getInstance() != null) {
        MCMediaPlayerService.getInstance().stopMusic();

    }
    MCSelectedTrackIdSingleton.getInstance().mCurrentSongId = 0;
    MCSelectedSongIdSingleton.getInstance().mCurrentSongId = 0;

    switch (position) {
    case 0:
        fragment = new MCTrackFragment();
        fragment.setArguments(args);
        fTransaction.replace(R.id.container, fragment,
                MCConstants.TRACK_TAG).commit();
        break;
    case 1:
        fragment = new MCPlaylistFragment();
        fragment.setArguments(args);
        fTransaction.replace(R.id.container, fragment,
                MCConstants.PLAYLIST_TAG).commit();
        break;
    case 2:
        fragment = new MCOfflineSongs();
        fragment.setArguments(args);
        fTransaction.replace(R.id.container, fragment,
                MCConstants.OFFLINE_TAG).commit();
        break;
    case 3:
        fragment = new MCOwnFeed();
        fragment.setArguments(args);
        fTransaction.replace(R.id.container, fragment,
                MCConstants.OWNFEED_TAG).commit();
        break;
    case 4:
        fragment = new MCCategories();
        fragment.setArguments(args);
        fTransaction.replace(R.id.container, fragment,
                MCConstants.CATEGORIES_TAG).commit();
        break;
    }

}

Inside the onCreate method of navigation drawer fragment class:

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Read in the flag indicating whether or not the user has demonstrated
    // awareness of the
    // drawer. See PREF_USER_LEARNED_DRAWER for details.
    SharedPreferences sp = PreferenceManager
            .getDefaultSharedPreferences(getActivity());
    mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);

    if (savedInstanceState != null) {
        mCurrentSelectedPosition = savedInstanceState
                .getInt(STATE_SELECTED_POSITION);
        mFromSavedInstanceState = true;
    }

    // Select either the default item (0) or the last selected item.
    selectItem(mCurrentSelectedPosition); //Select item called
}

Select item method is as shown below:

 private void selectItem(int position) {
    mCurrentSelectedPosition = position;
    if (mDrawerListView != null) {
        mDrawerListView.setItemChecked(position, true);
    }
    if (mDrawerLayout != null) {
        mDrawerLayout.closeDrawer(mFragmentContainerView);
    }
    if (mCallbacks != null) {
        mCallbacks.onNavigationDrawerItemSelected(position);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM