The use of a rolling label indicator and a sliding content page is a common design style of mobile phone applications. Common and well-known applications include wechat (home page), netease News, Toutiao and Zhihu. For those of you who have had a few years of Android development experience, there are two well-known open source projects on GitHub that do this: PagerSlidingTabStrip and JakeWharton’s ViewPagerIndicator, especially the latter, are some of the things you’ve probably used in your own projects. Of course, both open source libraries are available now, but we have more options, such as TabLayout introduced in this article.

Since I/O ended in 2014, Google has released a number of new controls in the Support Design package, including TabLayout. With the use of ViewPager and Fragment, TabLayout can help developers create sliding tabs in minutes. This article, the first in the Material Design series, will introduce two common usage scenarios of TabLayout: the top TAB page (such as Zhihu) and the bottom menu bar (such as wechat). Let’s take a look at the final result:

Top TAB.gif

Bottom menu.gif

Basic introduction to


We can define each Tab entry of a TabLayout in code, or we can create it by calling the newTab () method on the TabLayout object, for example:

TabLayout tabLayout = ... ; tabLayout.addTab(tabLayout.newTab().setText("Tab 1")); 
tabLayout.addTab(tabLayout.newTab().setText("Tab 2")); 
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));Copy the code

TabLayout width distribution mode, Indicator underline height, font color, select listening events and other methods can be seen on the official website. This article mainly discusses TabLayout common application scenarios, so the Settings of each attribute will not be read.

Top TAB


TabLayout requires the Android Design package to use, so we need to introduce the Design package in build.gradle:

compile 'com. Android. Support: design: 23.3.0'Copy the code

Add TabLayout and ViewPager controls to the layout file activity_tab_layout. 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"> <include layout="@layout/include_toolbar"/> <android.support.design.widget.TabLayout android:id="@+id/tl_tab" android:layout_width="match_parent" android:layout_height="@dimen/dp_48" android:background="@color/blue"> </android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:id="@+id/vp_content" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> </LinearLayout>Copy the code

Then let’s look at the code in TabLayoutActivity:

package com.yifeng.mdstudysamples;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;

import java.util.ArrayList;
import java.util.List;

/** * Created by yifeng on 16/8/3. * */
public class TabLayoutActivity extends BaseActivity {

    private TabLayout mTabTl;
    private ViewPager mContentVp;

    private List<String> tabIndicators;
    private List<Fragment> tabFragments;
    private ContentPagerAdapter contentAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab_layout);

        mTabTl = (TabLayout) findViewById(R.id.tl_tab);
        mContentVp = (ViewPager) findViewById(R.id.vp_content);

        initContent();
        initTab();
    }

    private void initTab(){
        mTabTl.setTabMode(TabLayout.MODE_SCROLLABLE);
        mTabTl.setTabTextColors(ContextCompat.getColor(this, R.color.gray), ContextCompat.getColor(this, R.color.white));
        mTabTl.setSelectedTabIndicatorColor(ContextCompat.getColor(this, R.color.white));
        ViewCompat.setElevation(mTabTl, 10);
        mTabTl.setupWithViewPager(mContentVp);
    }

    private void initContent(){
        tabIndicators = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            tabIndicators.add("Tab " + i);
        }
        tabFragments = new ArrayList<>();
        for (String s : tabIndicators) {
            tabFragments.add(TabContentFragment.newInstance(s));
        }
        contentAdapter = new ContentPagerAdapter(getSupportFragmentManager());
        mContentVp.setAdapter(contentAdapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_tab_layout, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.tab_add:
                tabIndicators.add("Tab " + tabIndicators.size());
                tabFragments.add(TabContentFragment.newInstance(tabIndicators.get(tabIndicators.size()- 1)));
                contentAdapter.notifyDataSetChanged();
                return true;

            case R.id.tab_mode_fixed:
                mTabTl.setTabMode(TabLayout.MODE_FIXED);
                return true;

            case R.id.tab_mode_scrollable:
                mTabTl.setTabMode(TabLayout.MODE_SCROLLABLE);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    class ContentPagerAdapter extends FragmentPagerAdapter{

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

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

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

        @Override
        public CharSequence getPageTitle(int position) {
            returntabIndicators.get(position); }}}Copy the code

The core code has two places, the first is the setupWithViewPager method to bind TabLayout and ViewPager together, so that the changes of both sides can directly affect the other side, free the developer to monitor the changes of both sides; The second is to override the getPageTitle method in the Adapter Adapter of the ViewPager, where the title of the label indicator is set.

Bottom menu bar


Above we use the system defined View to make a pure text and underline label indicator. In fact, we can also customize a layout and assign it to the Tab view of TabLayout, such as a wechat home page.

Compared to the top TAB indicator, the bottom menu bar simply places the TabLayout below:

<? 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"> <include layout="@layout/include_toolbar"/> <android.support.v4.view.ViewPager android:id="@+id/vp_content" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> </android.support.v4.view.ViewPager> <android.support.design.widget.TabLayout android:id="@+id/tl_tab" android:layout_width="match_parent" android:layout_height="@dimen/dp_56" android:background="@color/white"> </android.support.design.widget.TabLayout> </LinearLayout>Copy the code

In the Activity code, set the TabLayout height to 0 to hide the Indicator. Then get each Tab of the TabLayout by getTabAt (Position) and assign it to a custom layout view. The code is very simple:

package com.yifeng.mdstudysamples;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/** * Created by yifeng on 16/8/3. * */
public class TabLayoutBottomActivity extends BaseActivity {

    private TabLayout mTabTl;
    private ViewPager mContentVp;

    private List<String> tabIndicators;
    private List<Fragment> tabFragments;
    private ContentPagerAdapter contentAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab_layout_bottom);

        mTabTl = (TabLayout) findViewById(R.id.tl_tab);
        mContentVp = (ViewPager) findViewById(R.id.vp_content);

        initContent();
        initTab();
    }

    private void initTab(){
        mTabTl.setTabMode(TabLayout.MODE_FIXED);
        mTabTl.setSelectedTabIndicatorHeight(0);
        ViewCompat.setElevation(mTabTl, 10);
        mTabTl.setupWithViewPager(mContentVp);
        for (int i = 0; i < tabIndicators.size(); i++) {
            TabLayout.Tab itemTab = mTabTl.getTabAt(i);
            if(itemTab! =null){
                itemTab.setCustomView(R.layout.item_tab_layout_custom);
                TextView itemTv = (TextView) itemTab.getCustomView().findViewById(R.id.tv_menu_item);
                itemTv.setText(tabIndicators.get(i));
            }
        }
        mTabTl.getTabAt(0).getCustomView().setSelected(true);
    }

    private void initContent(){
        tabIndicators = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            tabIndicators.add("Tab " + i);
        }
        tabFragments = new ArrayList<>();
        for (String s : tabIndicators) {
            tabFragments.add(TabContentFragment.newInstance(s));
        }
        contentAdapter = new ContentPagerAdapter(getSupportFragmentManager());
        mContentVp.setAdapter(contentAdapter);
    }

    class ContentPagerAdapter extends FragmentPagerAdapter{

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

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

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

        @Override
        public CharSequence getPageTitle(int position) {
            returntabIndicators.get(position); }}}Copy the code

From these two use scenarios can be seen, the use of TabLayout to do a sliding TAB page or bottom menu bar, it is very convenient to achieve, the amount of code is not much, greatly reduce our development. However, TabLayout is not a panacea, if you want to make more special effects or we need to develop. Therefore, if you want to do a sliding label indicator, we strongly recommend to look at the TabLayout source code, I believe that you must have some inspiration.

The sample source code


I have created a Repository on GitHub to store the entire Android Material Design series of control learning cases. This Repository will be updated with the article.

Github.com/Mike-bel/MD…

Pay attention to the author


This article is created by Also Feng and first in also Feng’s personal blog, simultaneous authorization wechat public number: Technical bird (NiaoTech), welcome to pay attention to.