Now you can Subscribe using RSS

Submit your Email

Sunday

How to create Nested TabLayout with ViewPager in Android

Vishal Shrestha
Creating a nested TabLayout is pretty easy in Android. However, if you can figure out a layout that doesn't use nested TabLayout, then I suggest you choose it because it's better not to use nested tabLayout according to Google's guidelines. Since you are already here, I assume will not be satisfied without learning how to create nested tabLayout, so let's begin.

Check the Video of Nested TabLayout Here : Nested Tab Layout.

Nested TabLayout with ViewPager in Android
Nested TabLayout

In this example we will create tabLayouts with ViewPager which is the most common use of the two. One thing to decide is which ViewPager you want to make swipe-able, the container viewpager or the inner nested ViewPager, because both of them will have registered for touch events. So we need to disable the touch event for one of the viewPager. In this example we will make the main container tabLayout's viewpager non swipeable. Okay let's begin with the code now -

Creating Nested TabLayout with ViewPager in Android - 

1.First of all lets extend the ViewPager class to disable onTouchEvent with all other methods intact. If we don't do this, we will later have conflict when we create the nested ViewPager. Let's call class NonScrollableVP. Here's the code for it -   

public class NonScrollableVP extends ViewPager {
public NonScrollableVP(Context context) { 
 super(context); 
 }
public NonScrollableVP(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 }
@Override public boolean onInterceptTouchEvent(MotionEvent event) {
 // Never allow swiping to switch between pages
 return false;
 }
@Override public boolean onTouchEvent(MotionEvent event) { 
 // Never allow swiping to switch between pages return false; 
return false;
 } 

 
2. Now lets create the tabs for container tabLayout and ViewPager for container tabs. Let's call it main_tab_layout. Here's the XML code for it -

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

        <include layout="@layout/toolbar_layout"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabTextColor="#ffffff"
            app:tabSelectedTextColor="#ffffff"
            android:elevation="0dp"/>

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

    <kimera.facebooklogin.NonScrollableVP
        android:id="@+id/pagerMain"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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


Now create a Java class, let's call it MainTabs.java-

public class MainTabs extends Fragment {

    kimera.facebooklogin.NonScrollableVP mainPager;
    TabLayout tabs;
    Toolbar tb;

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_tab_layout);
        mainPager = (kimera.facebooklogin.NonScrollableVP)
                findViewById(R.id.pagerMain);
        tabs = (TabLayout) findViewById(R.id.tabs);
        tb = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(tb);
        setUpPager();
    }

    private void setUpPager() {

        MainNewsList news = new MainNewsList();
        MainExtraList extraList = new MainExtraList();
        MainPager adapter = new MainPager(getChildFragmentManager());
        adapter.addFragment(news, "NEWS");
        adapter.addFragment(extraList, "EXTRA");

        mainPager.setAdapter(adapter);
        tabs.setupWithViewPager(mainPager);

    }

    private class MainPager extends FragmentPagerAdapter {

        List<Fragment> mFragments = new ArrayList<>();
        List<String> mFragmentsTitle = new ArrayList<>();

        public MainPager(FragmentManager fm) {
            super(fm);
        }

        public void addFragment(Fragment f, String s) {
            mFragments.add(f);
            mFragmentsTitle.add(s);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Log.d("mylog", mFragmentsTitle.get(position));
            return mFragmentsTitle.get(position);
        }

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

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


NOTE - Don't get in a hurry to run the project now, you must be getting an error as we have not created the MainNewsList and MainExtraList classes that we have used as pages for the pager. Let's do it now.

3.Create child fragment with tabLayout and viewPager.

This is the child fragment that has tabLayout. It has recyclerView as pages for it's pager.
Here's the xml files you will need -
Let's call the first XML file scrollable_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.TabLayout
        android:id="@+id/tabScrollable"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


    <android.support.design.widget.ViewPager
        android:id="@+id/vpNews"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout> 



Now we have set up the nested ViewPager, let's create a recyclerView as it's contents. Create a new XML file, name it news_recycler_view.xml -

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/rvNews">

</android.support.v7.widget.RecyclerView>


Let's setup the layout of the row of the recyclerView. Create a new XML file and name it recycler_row-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/llRvRow">

    <TextView
        android:id="@+id/tvRv"
        android:padding="24dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>


We now have necessary XML files to proceed further. Now let's create a class, NewsList.java that will inflater the recyclerView rows-

public class NewsList extends Fragment {

    RecyclerView rvNewsList;

    public NewsList(){

    }

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

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setUpRecyclerView();
    }

    private void setUpRecyclerView() {
        List<String> content = new ArrayList<>();
        for(int i =0; i<5; i++)
        {
            content.add("content "+ i);
        }
        rvNewsList.setHasFixedSize(true);
        RecyclerView.LayoutManager lm = new LinearLayoutManager(getContext());
        rvNewsList.setLayoutManager(lm);
        MySimpleAdapter adapter = new MySimpleAdapter(content);
        rvNewsList.setAdapter(adapter);
    }
    private class MySimpleAdapter extends RecyclerView.Adapter{

        List<content> content = new ArrayList<>();

        public MySimpleAdapter(List<String> c){
            content.addAll(c);
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false);
            MyViewHolder vh = new MyViewHolder(v);
            return vh;
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            MyViewHolder vh = (MyViewHolder) holder;
            vh.tv.setText("Option " + position);
        }

        @Override
        public int getItemCount() {
            return content.size();
        }

        public class MyViewHolder extends RecyclerView.ViewHolder {
            public TextView tv;
            public MyViewHolder(View itemView) {
                super(itemView);
                tv = (TextView)itemView.findViewById(R.id.tvRv);
            }
        }
    }
}

Finally, we are toward's the end, now let's create a class MainNewsList.java that will handle the NEWS fragment that we created in the first part.

public class MainNewsList extends Fragment {

    LinearLayout mainLayout;
    TabLayout tabs;
    ViewPager vpNews;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mainLayout = (LinearLayout) inflater.inflate(R.layout.scrollable_tab, container, false);
        tabs = (TabLayout) mainLayout.findViewById(R.id.tabScrollable);
        vpNews = (ViewPager) mainLayout.findViewById(R.id.vpNews);
        setUpPager();
        return mainLayout;
    }

    private void setUpPager() {
        NewsPagerAdapter adp = new NewsPagerAdapter(getFragmentManager());
        NewsList n1 = new NewsList();
        NewsList n2 = new NewsList();
        NewsList n3 = new NewsList();
        NewsList n4 = new NewsList();
        NewsList n5 = new NewsList();

        adp.addFrag(n1, "World");
        adp.addFrag(n2, "Special");
        adp.addFrag(n3, "International");
        adp.addFrag(n4, "Technology");
        adp.addFrag(n5, "Finance");

        tabs.setTabMode(TabLayout.MODE_SCROLLABLE);
        vpNews.setAdapter(adp);
        vpNews.setOffscreenPageLimit(12);
        tabs.setupWithViewPager(vpNews);
    }

    private class NewsPagerAdapter extends FragmentPagerAdapter {

        List<Fragment> fragList = new ArrayList<>();
        List<String> titleList = new ArrayList<>();

        public NewsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        public void addFrag(Fragment f, String title) {
            fragList.add(f);
            titleList.add(title);
        }

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

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

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


Now just one simple fragment and we are good to go! Create an xml file named main_extra.xml-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Others features"
        android:id="@+id/textView"
        android:gravity="center" />
</LinearLayout>

  
Now we will create the corresponding java file for this layout. Let's name it MainExtraList.java -

public class MainExtraList extends Fragment {

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


And we are done! we have created a nested tabLayout with ViewPagers in Android. We've also learnt how to use recyclerViews in viewPager which is a more complex and practical application of this example. I know this seems complex at first, but you will get the hang of it once you understand the flow. If you have any questions don't hesitate to drop them in the comments section below. Happy coding!
Learn how to create scrollable tabs.

Vishal Shrestha / Author & Founder

A developer by profession, a born Adventurer. I mainly do Android but like to get my hands dirty with web development and a little bit of Python. I would't rather go on a Trek than a party and you can find me having a few rounds with the heavy bag to let out the steam ;)

For Business info : My Portfolio Site.

0 comments:

Post a Comment

Coprights @ 2017 | The Code City by Vishal Shrestha Vishal Shrestha