原文出处:http://chenfuduo.me/2015/07/30/TabLayout-of-design-support-library/
在开发中,我们常常需要ViewPager结合Fragment一起使用,如下图:
 1
1
我们可以使用三方开源的PagerSlidingTabStrip去实现,或者viewpagerindicator,我一般都偏向前者。现在我们可以使用Design support library库的TabLayout去实现了。最终的效果图:

效果图
创建布局
| <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <!--app:tabMode="scrollable"  这个属性我在代码中设置了-->
 <!-- tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);-->
 <android.support.design.widget.TabLayout
 android:id="@+id/sliding_tabs"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 />
 <android.support.v4.view.ViewPager
 android:id="@+id/viewpager"
 android:layout_width="match_parent"
 android:layout_height="0px"
 android:layout_weight="1"
 android:background="@android:color/white" />
 </LinearLayout>
 在xml添加TabLayout,如同ViewPager,直接`android.support.design.widget.TabLayout`即可。还有其他的属性我会在代码中设置。
 | 
创建Fragment
| package me.chenfuduo.myfragmentdemo.fragment;import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.v4.app.Fragment;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 import me.chenfuduo.myfragmentdemo.R;
 /**
 * Created by Administrator on 2015/7/30.
 */
 public class PageFragment extends Fragment {
 public static final String ARG_PAGE = "ARG_PAGE";
 private int mPage;
 public static PageFragment newInstance(int page) {
 Bundle args = new Bundle();
 args.putInt(ARG_PAGE, page);
 PageFragment pageFragment = new PageFragment();
 pageFragment.setArguments(args);
 return pageFragment;
 }
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 mPage = getArguments().getInt(ARG_PAGE);
 }
 @Nullable
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.fragment_page, container, false);
 TextView textView = (TextView) view;
 textView.setText("Fragment #" + mPage);
 return view;
 }
 }
 | 
其中Fragment的布局为:
| <?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:gravity="center" />
 | 
ViewPager的适配器
| package me.chenfuduo.myfragmentdemo.adapter;import android.content.Context;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentPagerAdapter;
 import me.chenfuduo.myfragmentdemo.fragment.PageFragment;
 /**
 * Created by Administrator on 2015/7/30.
 */
 public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
 final int PAGE_COUNT = 3;
 private String tabTitles[] = new String[]{"tab1","tab2","tab3"};
 private Context context;
 public SimpleFragmentPagerAdapter(FragmentManager fm,Context context) {
 super(fm);
 this.context = context;
 }
 @Override
 public Fragment getItem(int position) {
 return PageFragment.newInstance(position + 1);
 }
 @Override
 public int getCount() {
 return PAGE_COUNT;
 }
 @Override
 public CharSequence getPageTitle(int position) {
 return tabTitles[position];
 }
 }
 | 
设置TabLayout
| package me.chenfuduo.myfragmentdemo;import android.os.Bundle;
 import android.support.design.widget.TabLayout;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.view.ViewPager;
 import android.view.Menu;
 import android.view.MenuItem;
 import me.chenfuduo.myfragmentdemo.adapter.SimpleFragmentPagerAdapter;
 public class ThirdActivity extends FragmentActivity {
 private SimpleFragmentPagerAdapter pagerAdapter;
 private ViewPager viewPager;
 private TabLayout tabLayout;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_third);
 pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
 viewPager = (ViewPager) findViewById(R.id.viewpager);
 viewPager.setAdapter(pagerAdapter);
 tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
 tabLayout.setupWithViewPager(viewPager);
 tabLayout.setTabMode(TabLayout.MODE_FIXED);
 }
 }
 | 
这里提几点我遇到的问题
开始我设置的是:
| tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE); | 
运行后,三个TabLayout标签挤到一块去了。如下:

查看api,找到结果了。这个tabmode有两个属性值:
- MODE_FIXED:Fixed tabs display all tabs concurrently and are best used with content that benefits from quick pivots between tabs. 
- MODE_SCROLLABLE:Scrollable tabs display a subset of tabs at any given moment, and can contain longer tab labels and a larger number of tabs. 
不做过多的解释,MODE_SCROLLABLE适合很多tabs的情况。
查看下源码就知道了:
| public void setupWithViewPager(ViewPager viewPager) {PagerAdapter adapter = viewPager.getAdapter();
 if(adapter == null) {
 throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
 } else {
 ...
 }
 }
 | 
以上就是最基本的用法,是不是很简单。哈~
定义TabLayout的样式
默认的情况下,TabLayout的tab indicator的颜色是Material Design中的accent color(#009688),我们可以稍作修改:
| <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout"><item name="tabIndicatorColor">#0000FF</item>
 </style>
 | 
在布局中使用:
| <android.support.design.widget.TabLayoutandroid:id="@+id/sliding_tabs"
 style="@style/MyCustomTabLayout"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 />
 | 
还有一些其他的样式可供选择:
| <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout"><item name="tabMaxWidth">@dimen/tab_max_width</item>
 <item name="tabIndicatorColor">?attr/colorAccent</item>
 <item name="tabIndicatorHeight">2dp</item>
 <item name="tabPaddingStart">12dp</item>
 <item name="tabPaddingEnd">12dp</item>
 <item name="tabBackground">?attr/selectableItemBackground</item>
 <item name="tabTextAppearance">@style/MyCustomTabTextAppearance</item>
 <item name="tabSelectedTextColor">?android:textColorPrimary</item>
 </style>
 <style name="MyCustomTabTextAppearance" parent="TextAppearance.Design.Tab">
 <item name="android:textSize">14sp</item>
 <item name="android:textColor">?android:textColorSecondary</item>
 <item name="textAllCaps">true</item>
 </style>
 | 
添加icon到tab
当前的TabLayout没有方法让我们去添加icon,我们可以使用SpannableString结合ImageSpan来实现,在SimpleFragmentPagerAdapter中:
| private int[] imageResId = {R.drawable.ic_one,
 R.drawable.ic_two,
 R.drawable.ic_three
 };
 // ...
 @Override
 public CharSequence getPageTitle(int position) {
 // Generate title based on item position
 // return tabTitles[position];
 Drawable image = context.getResources().getDrawable(imageResId[position]);
 image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
 SpannableString sb = new SpannableString(" ");
 ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
 sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
 return sb;
 }
 | 
运行,发现没有显示,这是因为TabLayout创建的tab默认设置textAllCaps属性为true,这阻止了ImageSpan被渲染出来,可以通过下面的样式文件定义来改变:
| <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout"><item name="tabTextAppearance">@style/MyCustomTextAppearance</item>
 </style>
 <style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
 <item name="textAllCaps">false</item>
 </style>
 | 
现在运行,效果就出来了。
添加icon和text到tab
| @Overridepublic CharSequence getPageTitle(int position) {
 // Generate title based on item position
 Drawable image = context.getResources().getDrawable(imageResId[position]);
 image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
 // Replace blank spaces with image icon
 SpannableString sb = new SpannableString("   " + tabTitles[position]);
 ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
 sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
 return sb;
 }
 | 
我们看到在实例化SpannableString的时候,我在tabTitles[position]前面加了几个空格,这些空格的位置是用来放置icon的。
添加自定义的view到tab
适配器中增加getTabView(...)方法:
| package me.chenfuduo.myfragmentdemo.adapter;import android.content.Context;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentPagerAdapter;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 import me.chenfuduo.myfragmentdemo.R;
 import me.chenfuduo.myfragmentdemo.fragment.PageFragment;
 /**
 * Created by Administrator on 2015/7/30.
 */
 public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
 final int PAGE_COUNT = 3;
 private String tabTitles[] = new String[]{"tab1", "tab2", "tab3"};
 private int[] imageResId = {R.drawable.avatar_enterprise_vip,
 R.drawable.avatar_grassroot,
 R.drawable.avatar_vip};
 private Context context;
 public SimpleFragmentPagerAdapter(FragmentManager fm, Context context) {
 super(fm);
 this.context = context;
 }
 @Override
 public Fragment getItem(int position) {
 return PageFragment.newInstance(position + 1);
 }
 @Override
 public int getCount() {
 return PAGE_COUNT;
 }
 @Override
 public CharSequence getPageTitle(int position) {
 //第一次的代码
 //return tabTitles[position];
 //第二次的代码
 /**
 Drawable image = context.getResources().getDrawable(imageResId[position]);
 image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
 SpannableString sb = new SpannableString(" " + tabTitles[position]);
 ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
 sb.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 return sb;*/
 return null;
 }
 public View getTabView(int position){
 View view = LayoutInflater.from(context).inflate(R.layout.tab_item, null);
 TextView tv= (TextView) view.findViewById(R.id.textView);
 tv.setText(tabTitles[position]);
 ImageView img = (ImageView) view.findViewById(R.id.imageView);
 img.setImageResource(imageResId[position]);
 return view;
 }
 }
 | 
简单的布局:
| <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 >
 <ImageView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:id="@+id/imageView"
 android:layout_centerVertical="true"
 />
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_toRightOf="@id/imageView"
 android:layout_centerVertical="true"
 android:id="@+id/textView"
 android:layout_marginLeft="3dp"
 />
 </RelativeLayout>
 | 
使用:
| @Overrideprotected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_third);
 pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
 viewPager = (ViewPager) findViewById(R.id.viewpager);
 viewPager.setAdapter(pagerAdapter);
 tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
 tabLayout.setupWithViewPager(viewPager);
 tabLayout.setTabMode(TabLayout.MODE_FIXED);
 for (int i = 0; i < tabLayout.getTabCount(); i++) {
 TabLayout.Tab tab = tabLayout.getTabAt(i);
 tab.setCustomView(pagerAdapter.getTabView(i));
 }
 }
 | 
处理配置改变
当屏幕旋转或者配置改变的时候,我们需要保存当前的状态。
| @Overridepublic void onSaveInstanceState(Bundle outState) {
 super.onSaveInstanceState(outState);
 outState.putInt(POSITION,tabLayout.getSelectedTabPosition());
 }
 @Override
 protected void onRestoreInstanceState(Bundle savedInstanceState) {
 super.onRestoreInstanceState(savedInstanceState);
 viewPager.setCurrentItem(savedInstanceState.getInt(POSITION));
 }
 | 
需要注意的是getSelectedTabPosition()方法是最新的design support library才有的。
最后的效果如下:

												
												
						- android design library提供的TabLayout的用法
		在开发中,我们常常需要ViewPager结合Fragment一起使用,如下图: 我们可以使用三方开源的PagerSlidingTabStrip去实现,或者viewpagerindicator,我一般都 ... 
- Android - 用Fragments实现动态UI - 使用Android Support Library
		Android Support Library提供了一个带有API库的JAR文件来让你可以在使用最新的Android API的同时也也已在早期版本的Android上运行.例如,Support Libr ... 
- 【Android】10.2 使用Android Support Library增强组件功能
		分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 Android Support Library提供了一些非常漂亮的附加功能,由于这些库的引用办法都差不多,所以这一 ... 
- Android Design Support Library(一)用TabLayout实现类似网易选项卡动态滑动效果
		这里我们用TabLayout来实现这一效果.TabLayout是Android Design Support Library库中的控件.Google在2015的IO大会上,给我们带来了更加详细的Mat ... 
- Android Design Support Library使用详解
		Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ... 
- 【转】【翻】Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏
		转自:http://mrfufufu.github.io/android/2015/07/01/Codelab_Android_Design_Support_Library.html [翻]Andro ... 
- Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏
		原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session--Make your app fanc ... 
- Material Design 开发利器:Android Design Support Library 介绍
		转自:https://blog.leancloud.cn/3306/ Android 5.0 Lollipop 是迄今为止最重大的一次发布,很大程度上是因为 material design —— 这是 ... 
- Android Design Support Library(三)用CoordinatorLayout实现Toolbar隐藏和折叠
		此文的代码在Android Design Support Library(一)用TabLayout实现类似网易选项卡动态滑动效果代码的基础上进行修改,如果你没有看过本系列的第一篇文章最好先看一看.Co ... 
随机推荐
	
									- Linux环境下安装中山大学东校区iNode客户端
			在中山大学登录校园网有两种方式,一种是连接WiFi,另一种是连接网线.这两种上网方式都需要用到NetID,但是连接网线的话还需要使用到iNode客户端(指东校区). Windows下iNode客户端的 ... 
- ONVIF协议客户端
			前几天跟大家聊了一些关于ONVIF的一些基础知识,它的工作原理以及优势.今天安徽思蔷信息科技为带大家了解一下simpleonvif 百度云盘下载地址:链接:https://pan.baidu.com/ ... 
- adb 安装与使用(一)
			一.ADB简介 1. 什么是adb? adb(Android Debug Bridage)是Android sdk的一个工具: adb 是用来连接安卓手机和PC端的桥梁,要有adb作为二者之间的维系, ... 
- Excel 读写
			一.环境准备:pom.xml 导入依赖 poi-ooxml <dependencies> <dependency> <groupId>org.apache.poi& ... 
- Django 中间件 详细总结
			一.什么是中间件 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出.因为改变的是全局,所以需要谨慎实用,用不好会影 ... 
- 基于ABP开发框架的技术点分析和项目快速开发实现
			在我们开发各种项目应用的时候,往往都是基于一定框架进行,同时配合专用的代码生成工具,都是为了快速按照固定模式开发项目,事半功倍,本篇随笔对基于ABP开发框架的技术点进行分析和ABP框架项目快速开发实现 ... 
- React-Router基础(<HashRouter>)
			<Router>使用URL(即window.location.hash)的哈希部分来保持UI与URL同步的A. 重要说明:哈希历史记录不支持location.key或location.st ... 
- Linux驱动实践:带你一步一步编译内核驱动程序
			作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ... 
- 为什么MySQL字符串不加引号索引失效?《死磕MySQL系列 十一》
			群里一个小伙伴在问为什么MySQL字符串不加单引号会导致索引失效,这个问题估计很多人都知道答案.没错,是因为MySQL内部进行了隐式转换. 本期文章就聊聊什么是隐式转换,为什么会发生隐式转换. 系列文 ... 
- Java是“值传递”还是“引用传递”?
			本文是根据stackoverflow网站上的一道题目整理出来的. Java一直是"值传递"而不是引用传递.看一个例子: public class Main{ public stat ...