So I've recently been working on updating my app to use the new material design support library. My application has one main activity with a drawerLayout and navigation view. The main content of app is shown in a frameLayout, through fragments. However, I am trying now to add material tabs to one of the navigation drawer's fragments. However, I am not sure how to implement this while keeping my fragments in the nav drawer functioning. A good example of what I am trying to achieve is shown below:
In this app (Google play music), only some of the navigation drawer's items have tabs while others do not. So my question is, how would I implement this? (Not looking for code, just an overview of how my layout should be organized)
To recap/clarify: I have a main layout with a frameLayout (for my app's content), and a navigationView (for navigating the different item fragments). I then have a listener which replaces the main layout's frameLayout with the item's respective fragment. Now, I need to add tabs to just one of these fragments (to navigate between 4 other fragments). I am also using a toolbar which I include as a separate layout.
Any advice is appreciated. I'm sorry if my description is a little confusing; I will clarify any necessary details.
Ok suppose your NavigationView has two options, the first one displays the fragment with tabs (tab layout) and the second one displays just a fragment with a toolbar. You have two options then:
I prefer the second option to avoid having to always configure the toolbar so this is what I did once:
<!-- layout_main -->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:tabGravity="fill"
app:tabMode="fixed" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
<!-- The NavigationView -->
<fragment
android:id="@+id/navigation_fragment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="some.path.to.the.NavigationViewFragment"
tools:layout="@layout/fragment_navigation_view" />
</android.support.v4.widget.DrawerLayout>
As you see I change the visibility of TabLayout to "gone" so that the fragment with tabs take care to set as visible. The Fragment with the tabs just have the ViewPager in the Layout:
<!-- fragment_with_tabs -->
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Now the fragment with tabs initialize the ViewPager with the fragments for each page:
@Override
public onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// The getChildFragmentManager() is Very important! Because fragments inside fragments are
// not supported with the tipical fragmentManager, it requires NestedFragments and those
// uses a childFragmentManager(). In other case a strange behaviour occurs
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new TabOneFragment(), "Tab 1");
adapter.addFragment(new TabTwoFragment(), "Tab 2");
viewPager.setAdapter(adapter);
tabLayout = (TabLayout) getActivity().findViewById(R.id.tab_layout);
tabLayout.setVisibility(View.VISIBLE);
tabLayout.setupWithViewPager(viewPager);
}
And finally do whatever you want in your TabFragments, this works fine for me and I hope this be useful for you too. Sorry for some problem with code syntax, I develop android with Kotlin and not with Java.
I can't recommend what Yiyo suggested. If you are going to have Fragments with different layouts, you should let the Fragments customize these layouts in the XML. This is why the introduction of Toolbar made so much sense for Android development. In the future, you might even have more requirements that differ between each Fragment. Some of them might not want a Toolbar, some of them might need another View above the Toolbar, some of them will have a RecyclerView that you would like to be accessible to the CoordinatorLayout and AppBar so that the scrolling behavior works properly.
I recommend you to put only a FrameLayout as the content of your DrawerLayout (as Yiyo mentioned in point 1). Here you will load each Fragment from the callbacks of the NavigationView.
<android.support.v4.widget.DrawerLayout
...
android:fitsSystemWindows="true"
>
<FrameLayout
android:id="@+id/drawer_content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.NavigationView
...
/>
</android.support.v4.widget.DrawerLayout>
In each Fragment's XML you will put, if required by that Fragment, a Toolbar. In your tabbed Fragment's XML you will put the TabLayout, and if you so wish, the CoordinatorLayout and AppBarLayout. From each Fragment that has a Toolbar, you will set the Toolbar as the ActionBar:
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);
That's all there is to it. Of course you don't want to repeat yourself in every Fragment, so you can, for example, put this code in a DrawerFragment and subclass it for fragments with a Toolbar. You will also want to put your Toolbar XML configuration in a single file and include it in the Fragment's XML <include layout="@layout/toolbar" />
. Or you might want to remove the Toolbar from some fragments, or change its color, theme, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With