Search code examples
androidandroid-fragmentsfragmenttransaction

How to get Activity containerViewId from click event on item in ViewPager fragment nested in NavigationView Fragment?


I have an Activity with a NavigationView.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.example.app.MainActivity">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_scrollFlags="scroll"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </android.support.design.widget.AppBarLayout>

        <RelativeLayout 
            android:id="@+id/containerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" ></RelativeLayout>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:src="@android:drawable/ic_dialog_email" />

    </android.support.design.widget.CoordinatorLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

</android.support.v4.widget.DrawerLayout>

On starting the app, or on clicking a NavigationView item, the following is called:

fragmentManager.beginTransaction().replace(R.id.containerView, new NavFragment()).commit();

where:

FragmentManager fragmentManager = getSupportFragmentManager();

NavFragment has the following layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:id="@+id/tabContainer">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="fixed"
            app:tabGravity="fill"
            android:theme="@style/AppTheme.AppBarOverlay"
            android:background="@color/colorPrimary"/>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout>

and contains a tabbed ViewPager:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.nav_frag, container, false);
        ViewPager viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
        TabLayout tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);

        setupViewPager(viewPager);
        tabLayout.setupWithViewPager(viewPager);

        return rootView;
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
        String tab1 = getResources().getString(R.string.tab_1);
        String tab2= getResources().getString(R.string.tab_2);
        String tab3 = getResources().getString(R.string.tab_3);

        adapter.addFragment(new Frag1(), tab1);
        adapter.addFragment(new Frag2(), tab2);
        adapter.addFragment(new Frag3(), tab3);
        viewPager.setAdapter(adapter);
    }

class ViewPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

Then each ViewPager fragment contains its own RecyclerView with items.

Now my question is what do I put in the onClick for the RecyclerView items in the nested ViewPager tabs, calls the same main container, containView that is in the MainActivity layout? That is, how do I reference that container? Basically, I need the new fragment to replace the tablayout and ViewPager. Then on clicking the back button, for it to return to the ViewPager location where the item was clicked, the way it would happen when calling new activity. Think along the lines of:

fragmentManager.beginTransaction().replace(R.id.containerView, new ClickedItemFrag()).commit();

The point of calling a fragment instead of a new activity is to maintain everything inside the NavigationView. I've looked and looked, but I can't find a working solution to my dilemma of trying to reference the containerView.

Thanks in advance.

EDIT: I tried to use:

fragmentManager.beginTransaction().replace(((ViewGroup)getView().getParent()).getId(), ClickedItemFrag()).commit();

gives:

09-27 12:48:16.720 17000-17000/com.example.app E/FragmentManager: No view found for id 0x7f0d0138 (com.example.app:id/viewpager) for fragment ClickedItemFrag{b189f1c #0 id=0x7f0d0138}

Then:

fragmentManager.beginTransaction().replace(((ViewGroup)getView().getParent().getParent()).getId(), ClickedItemFrag()).commit();

gives:

09-27 12:43:12.999 13621-13621/com.example.app E/FragmentManager: No view found for id 0x7f0d0135 (com.example.app:id/tabContainer) for fragment ClickedItemFrag{68c33f0 #0 id=0x7f0d0135}

Then:

fragmentManager.beginTransaction().replace(((ViewGroup)getView().getParent().getParent().getParent()).getId(), ClickedItemFrag()).commit();

gives:

java.lang.IllegalArgumentException: No view found for id 0x7f0d0075 (com.example.app:id/containerView) for fragment ClickedItemFrag{4f136ab #0 id=0x7f0d0075}

Solution

  • Inside your Activity which contains all your Layout add the method navigateToFragment():

    class MainActivity extends Activity {
    
        // ..Your code here
    
        public void navigateToFragment(Fragment fragment) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.containerView, fragment)
                    .addToBackStack(null)
                    .commit();
        }
    }
    

    Then when an item inside your RecyclerView is clicked you call navigateToFragment() from your Frag1, Frag2, Frag3 fragments:

    ((MainActivity) getActivity()).navigateToFragment(new ClickedItemFrag());