1. 简介

1.TabLayout给我们提供的是一排横向的标签页

2.#newTab()这个方法来创建新的标签页,然后用过#setText()和#setIcon方法分别修改标签页的文本和图标,创建完成之后,我们需要使用#addtab()方法把他加到TabLayout中显示出来

3.第二种添加标签的方式就是直接在TabLayout布局下添加#TabItem控件

4.对于TabLayout在标签之前的切换事件我们可以通过注册一个监听器来处理,#setOnTabSelectedListener(OnTabSelectedListener)

5.TabLayout可以和ViewPager一起使用


2. 自定义属性值

TabLayout属性

属性 意义
tabGravity fill,填满TabLayout;center,居中显示
tabMode fixed, 固定标签;scrollable,可滚动标签,个数较少的时候可以使用fixed,如果标签超出了屏幕范围,设置为scrollable比较好
tabMaxWidth Tab的最大宽度
tabIndicatorColor 底部滑动的线条的颜色,默认是colorAccent
tabIndicatorHeight 底部滑动线条的高度
tabPadding* 标签页的padding
tabBackground 标签页的背景
tabTextAppearance 文本设置
tabSelectedTextColor 选中字体颜色

TabItem属性

属性 意义
text 标签文字
icon 图标
layout 自定义布局

3. 源码分析

一点一点的看


类成员 稍微解释一下
Mode MODE_SCROLLABLE, MODE_FIXED两种模式,一个是固定,一个是可滚动
TabGravity GRAVITY_FILL, GRAVITY_CENTER,两种摆放方式,铺满和居中
OnTabSelectedListener Tab切换事件的回调接口
Tab类 对TabView进行的封装,给它加了一些属性,因为TabView无法对外暴露,相当于给外部提供一个调用的类,值得一提的是这个tag是一个object,所以可以往里面存放各种内容,传递数据的时候可能会有用
TabLayoutOnPageChangeListener 继承 ViewPager.OnPageChangeListener用于与ViewPager联动,主要是indicator的动作和tab页的选中
ViewPagerOnTabSelectedListener 继承TabLayout.OnTabSelectedListener,viewpager用来配合tablayout的页面切换事件

方法 稍微解释一下
构造方法 不显示滚动条,创建标签条就是下面滚来滚去的那个东东,获取自定义属性值
addTab 手动添加Tab页
addOnTabSelectedListener/removeOnTabSelectedListener、clearOnTabSelectedListeners 添加/移除/清空Tab选择事件监听器
newTab 创建Tab页
getTabAt 通过index获取Tab
removeTab 通过tab实例移除tab
removeTabAt 移除特定位置的tab
removeAllTabs 清空tabs
setTabTextColors 设置tab的正常显示颜色和选中后颜色
setupWithViewPager 通过ViewPager初始化TabLayout
shouldDelayChildPressedState 判断是否需要delay视图的press状态,一般无法滚动的视图直接返回false,可以滚动的视图看情况返回true或者false
addView 添加TabItem,如果参数类型不是TabItem会报异常
generateLayoutParams 默认生成属性值,防止TabItem没有定义android:layout_*而报异常



结合上面的介绍,这些内容含义应该比较清晰了


4. 简单使用

不使用setupWithViewPager,与ViewPager联动

布局文件

<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="onlyloveyd.com.indicatordemo.MainActivity"> <android.support.design.widget.TabLayout
android:id="@+id/tb_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWhite"
app:tabGravity="fill"
app:tabIndicatorColor="@color/colorAccent"
app:tabIndicatorHeight="4dp"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/colorAccent"
app:tabTextColor="@color/colorBlack"> <android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/one"
android:text="社会"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/two"
android:text="娱乐"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/three"
android:text="体育"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/four"
android:text="军事"/> </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"/>
</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.activity_main)
LinearLayout activityMain;
@BindView(R.id.vp_content)
ViewPager vpContent;
@BindView(R.id.tb_title)
TabLayout tbTitle; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
MainPagerAdapter mainPagerAdapter = new MainPagerAdapter(getSupportFragmentManager());
vpContent.setAdapter(mainPagerAdapter);
tbTitle.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(vpContent));
vpContent.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tbTitle));
} }

关键点在最后两行代码

tbTitle.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(vpContent));
vpContent.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tbTitle));

这两行代码来源于TabLayout的setupWithViewPager方法,目的就是为了实现ViewPager和TabLayout的联动,但是也不用removeAllTabs,看过这部分源码的朋友应该都知道,setupWithViewPager方法中先清除tab,然后根据ViewPager的getPagerTitle返回的字符串创建文字Tab并且添加到TabLayout中用于与ViewPager联动,这就是为啥很多初学者在使用setupWithViewPager的时候出现tab页无法显示的问题一般原因都是自己添加了tab或者是在布局文件中定义了TabItem但是使用的时候调用了setupWithViewPager方法,但是ViewPager的Adapter又没有复写getPagerTitle方法,因为这个方法在PagerAdapter中实默认返回null的。同时还有一个弊端就是setupWithViewPager并不支持图标显示。,原因就是:



而在populateFromPagerAdapter的实现中

    void populateFromPagerAdapter() {
removeAllTabs();//一开始就把全部的tab给干掉 if (mPagerAdapter != null) {
final int adapterCount = mPagerAdapter.getCount();//获取ViewPager的数量
for (int i = 0; i < adapterCount; i++) {
addTab(newTab().setText(mPagerAdapter.getPageTitle(i)), false);//只拿title,没有设置icon
} // Make sure we reflect the currently set ViewPager item
if (mViewPager != null && adapterCount > 0) {
final int curItem = mViewPager.getCurrentItem();
if (curItem != getSelectedTabPosition() && curItem < getTabCount()) {
selectTab(getTabAt(curItem));
}
}
}
}

实际效果


使用setupWithViewPager,与ViewPager联动

既然setupWithViewPager会清除TabItem,那么我们就不添加TabItem,让它自己处理吧

布局文件去掉上个例子中的四个TabItem


MainActivity中去掉后面两行,换成如下一行代码

tbTitle.setupWithViewPager(vpContent);

实际效果

虽说setupWithViewPager本身的实现过程是不支持Icon的显示的,但是我们可以自己动手,一个简单的循环解决问题,实现的效果与上面4.1节相同

for(int index = 0 ; index< tbTitle.getTabCount(); index++) {
TabLayout.Tab tab = tbTitle.getTabAt(index);
tab.setIcon(MainPagerAdapter.mIcons[index]);
}

5. 自定义Layout的TabItem

图标+文字

布局文件

<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="onlyloveyd.com.indicatordemo.MainActivity"> <android.support.design.widget.TabLayout
android:id="@+id/tb_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWhite"
app:tabGravity="fill"
app:tabIndicatorColor="@color/colorAccent"
app:tabIndicatorHeight="4dp"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/colorAccent"
app:tabTextColor="@color/colorBlack"> <android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/one"
android:layout="@layout/custom_indicator"
android:text="社会"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/custom_indicator2"
android:icon="@drawable/two"
android:text="娱乐"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/custom_indicator3"
android:icon="@drawable/three"
android:text="体育"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/four"
android:text="军事"/>
</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"/>
</LinearLayout>

使用自定义布局

android:layout=”@layout/custom_indicator”

android:layout=”@layout/custom_indicator2”

android:layout=”@layout/custom_indicator3”

custom_indicator.xml文件内容,值得注意的是这里的TextView的id必须是“@android:id/text1”,ImageView的id必须是“@android:id/icon”,原因来自于与TabLayout的源码中TabView的update方法。

custom_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"> <TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
/>
<ImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>

其他的两个文件和这个类似,只是位置调整了一哈子。


实际效果

6. 写在最后

2017年就从这篇博客开始吧~ 有问题请留言,方便的话 , 帮忙顶一下,谢谢!

<Android 基础(三十四)> TabLayout 从头到脚的更多相关文章

  1. Android笔记三十四.Service综合实例二

    综合实例2:client訪问远程Service服务 实现:通过一个button来获取远程Service的状态,并显示在两个文本框中. 思路:如果A应用须要与B应用进行通信,调用B应用中的getName ...

  2. <Android 基础(十四)> selector

    介绍 A StateListDrawable is a drawable object defined in XML that uses a several different images to r ...

  3. Bootstrap <基础三十二>模态框(Modal)插件

    模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果您想要单独引用该插件的功能,那么您需要引用  ...

  4. Bootstrap <基础三十>Well

    Well 是一种会引起内容凹陷显示或插图效果的容器 <div>.为了创建 Well,只需要简单地把内容放在带有 class .well 的 <div> 中即可.下面的实例演示了 ...

  5. Bootstrap<基础二十四> 缩略图

    Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ...

  6. JAVA之旅(三十四)——自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫

    JAVA之旅(三十四)--自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫 我们接着来说网络编程,TCP 一.自定义服务端 我们直接写一个服务端,让本机去连接 ...

  7. Gradle 1.12用户指南翻译——第三十四章. JaCoCo 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  8. spring boot 常见三十四问

    Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一 Spring Boot.Spring MVC 和 Spring 有什么区别 ...

  9. Java15-java语法基础(十四)抽象类

    Java15-java语法基础(十四)抽象类 一.抽象类的作用 三个类都有"执行任务"的方法,分别在这三个类中进行定义,因此需要重复编写代码,降低了程序开发效率,且增加了程序出现错 ...

  10. “全栈2019”Java多线程第三十四章:超时自动唤醒被等待的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. Ubuntu 14.04TLS和CentOS-6(64bit)上安装Nginx

    Ubuntu 14.04上安装Nginx [参考地址]https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on- ...

  2. 课程二(Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization),第二周(Optimization algorithms) —— 2.Programming assignments:Optimization

    Optimization Welcome to the optimization's programming assignment of the hyper-parameters tuning spe ...

  3. C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

    本文只介绍了比较方法,但是EndsWith,IndexOf等方法均采用相同的过程,先设置CultureInfo(一般情况下调用当前线程的CultureInfo,该语言文化可以通过控制面板设置),然后调 ...

  4. javascript中对条件判断语句的优化 分类: JavaScript 2015-06-07 09:54 832人阅读 评论(2) 收藏

    不管写什么程序,平时都会用到条件语句,如:if...else... switch这样的语句,来达到对条件的判断.下面看来一段代码: function abc(test){ if (test == 1) ...

  5. linux使用find和crontab命令定期清理过期文件

    crontab 命令 crontab 命令是 Linux 中用来设定重复执行命令或脚本的工具.它能够在指定的时间段内,按照需求以某一时间间隔执行命令或脚本. crontab 的基本用法 crontab ...

  6. 有意思的App

    掘金 javadoop 专业相机也羡慕奖 – Focos 说个睡前故事 so easy 奖 – 洪恩双语绘本 效率蹭蹭上升奖 – Sorted³ 时光隧道走一回奖 – NOMO 相机 设计师也爱用奖 ...

  7. Linux 启动过程详解

    目录 1. Linux启动过程 2. 启动过程概述 3. 引导加载阶段 4. 内核阶段 4.1 内核加载阶段 4.2 内核启动阶段 5. 早期的用户空间 6. 初始化过程 6.1 SysV init ...

  8. JAVA NIO:Buffer.mark()的用法

    在默认情况下,Buffer.mark()并没有什么用处,既不会影响Buffer的遍历,也不会影响Buffer的位置统计函数,如remaining()函数,能影响这些操作的行为只有position(). ...

  9. 在Idea2017.1中编译时发生如下的错误

    错误 在Idea2017.1中编译时发生如下的错误 Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8 Information:java: Errors ...

  10. Leetcode 763. Partition Labels

    思路:动态规划.对于属于coins的coin,只要知道amount-coin至少需要多少个货币就能表示,那么amount需要的货币数目=amount-coin需要的货币数目+1:如果amount-co ...