前言
之前讲过一篇TabLayout实现顶部导航的文章,这篇文章,来详细介绍下TabLayout的一些基本使用,让大家以后更加方便的使用。
这篇文章涉及的内容有:
- 控件库的导入
- TabLayout导航UI的快速实现
- TabLayout均分显示的问题
- 设置TabLayout选中和没选中时字体颜色
- 改变指示器下标的颜色
- 改变整个TabLayout的颜色
- 改变TabLayout内部字体大小
- 改变指示器下标的高度
- 添加图标
- 加入Padding
- Tab的宽度限制
- Tab的“Margin”
- 和ViewPager的联动
- 默认选中某项
- 监听事件
- TabLayout点击事件
一.控件库的导入
TabLayout属于android的Design库中的控件,所以需要在使用之前在项目的app对应的buildle.gradle中导入该库:
//TabLayout
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
二.TabLayout导航UI的快速实现
TabLayout导航ui的实现有两种方式,xml的实现和代码的实现。
1.1 xml实现TabLayout导航栏
直接在TabLayout内部加入TabItem即可,
1.2 代码实现TabLayout导航栏
先声明一个导航 代码实现如下:
@BindView(R.id.tablayout)
TabLayout mTabLayout;
private String mTitles[] = {
"上海", "头条推荐", "生活", "娱乐八卦", "体育",
"段子", "美食", "电影", "科技", "搞笑",
"社会", "财经", "时尚", "汽车", "军事",
"小说", "育儿", "职场", "萌宠", "游戏",
"健康", "动漫", "互联网"};
//TabLayout的基本使用
for(int i=0;i<4;i++){
TabLayout.Tab tab=mTabLayout.newTab();
tab.setTag(i);
tab.setText(mTitles[i]);
mTabLayout.addTab(tab);
}
这两种方法的区别是xml添加的只能是固定的几个item,若item的个数超过一屏宽度则不能使用这种方式布局,而代码布局则能实现item的个数超过一屏宽度的布局。
下面给出效果图:
三.TabLayout均分显示的问题
当导航过多的时候,使用app:tabMode="scrollable"属性,能实现滑动均分,当导航不足一屏的时候,去掉app:tabMode="scrollable"才能实现均分展示.
xml中显示如下:
代码如下:
for(int i=0;i<4;i++){
TabLayout.Tab tab=mTabLayout.newTab();
tab.setTag(i);
tab.setText(mTitles[i]);
mTabLayout.addTab(tab);
}
效果图:
当item个数很多的时候,xml代码如下:
代码如下:
//TabLayout的基本使用
for(int i=0;i
效果图如下:
四.设置TabLayout选中和没选中时字体颜色
设置选中和没选中的颜色可以在xml中设置,也可以在代码中设置
4.1xml中设置
4.2代码中设置
代码中设置的时候,xml不需要做相关设置:
代码设置如下:
//设置tab文本的没有选中(第一个参数)和选中(第二个参数)的颜色
mTabLayout.setTabTextColors(Color.GREEN, Color.RED);
效果图如下:
五. 改变指示器下标的颜色
直接在xml中设置:app:tabIndicatorColor="@color/green",xml代码如下:
效果图如下:
六. 改变整个TabLayout的颜色
直接在xml中设置:app:tabBackground="@color/blue",xml代码如下:
效果图:
七.改变TabLayout内部字体大小
直接在xml中设置:app:tabTextAppearance="@android:style/TextAppearance.Holo.Large",只有这一种设置方法,文字大小固定,比较不灵活,代码如下:
效果图如下:
八.改变指示器下标的高度
直接在xml中设置:app:tabIndicatorHeight="6dp",代码如下:
效果图如下:
当设置指示器的高度为0dp,或者设置指示器颜色透明,即可实现没有下标指示器的效果,这里我设置的是高度为0dp:
效果图如下:
九.添加图标
添加图标可以直接调用 TabLayout.Tab 的 setIcon() 方法,例如要新添加一个Tab1,并在Tab1上加一个 ic_launcher 图标,你可以像这样:
//添加图标
mTabLayout.addTab(mTabLayout.newTab().setText("Tab 1").setIcon(R.mipmap.ic_launcher));
效果图:
十. 加入Padding
设置Tab内部的子控件的Padding:
app:tabPadding="xxdp"
app:tabPaddingTop="xxdp"
app:tabPaddingStart="xxdp"
app:tabPaddingEnd="xxdp"
app:tabPaddingBottom="xxdp"
设置整个TabLayout的Padding:
app:paddingEnd="xxdp"
app:paddingStart="xxdp"
十一.Tab的宽度限制
设置最大的tab宽度:
app:tabMaxWidth="xxdp"
设置最小的tab宽度:
app:tabMinWidth="xxdp"
十二.Tab的“Margin”
TabLayout开始位置的偏移量:
app:tabContentStart="50dp"
十三.和ViewPager的联动
之前已经讲过和ViewPager联动的一篇文章了,这里就不做详细讲解了。
十四.默认选中某项
如果你要设置默认选中第三项,你可以这样:
mTabLayout.getTabAt(2).select();
十五.监听事件
监听事件如下:
//监听事件
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
//选中了tab的逻辑
LogUtil.i("======我选中了===="+tab.getTag());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
//未选中tab的逻辑
LogUtil.i("======我未被选中===="+tab.getTag());
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
//再次选中tab的逻辑
LogUtil.i("======我再次被选中===="+tab.getTag());
}
});
这里需要注意的是,初始化进入的时候,监听事件的三个方法都不会执行,假设此时你的item选中的是index=0,当你点击index=1的那项时,onTabUnselected(TabLayout.Tab tab)执行的是index=0的tab,onTabSelected(TabLayout.Tab tab)会执行index=1的Tab,此时onTabReselected(TabLayout.Tab tab)不会执行。当item已经选中的是index=1的时候,你再点击这个index=1的item的时候,onTabSelected(TabLayout.Tab tab)和onTabUnselected(TabLayout.Tab tab)不会执行,onTabReselected(TabLayout.Tab tab)会执行,tab为你当前点击的tab。
十六.TabLayout点击事件
只需调用以下方法:
/**TabLayout点击事件**/
private void tabItemClick(){
//if(!mTabLayout.getTabAt(position).isSelected())是为了实现选中后再响应点击事件,
//TabLayout和ViewPager联合使用的时候会用到
for (int i = 0; i < mTabLayout.getTabCount(); i++){
TabLayout.Tab tab = mTabLayout.getTabAt(i);
if (tab == null) return;
//这里使用到反射,拿到Tab对象后获取Class
Class c = tab.getClass();
try {
//Filed “字段、属性”的意思,c.getDeclaredField 获取私有属性。
//"mView"是Tab的私有属性名称(可查看TabLayout源码),类型是 TabView,TabLayout私有内部类。
Field field = c.getDeclaredField("mView");
//值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
//如果不这样会报如下错误
// java.lang.IllegalAccessException:
//Class com.test.accessible.Main
//can not access
//a member of class com.test.accessible.AccessibleTest
//with modifiers "private"
field.setAccessible(true);
final View view = (View) field.get(tab);
if (view == null) return;
view.setTag(i);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (int) view.getTag();
//这里就可以根据业务需求处理点击事件了。
if(!mTabLayout.getTabAt(position).isSelected()){
return;
}
switch (position) {
case 0:
showShort("我是0");
break;
case 1:
showShort("我是1");
break;
case 2:
showShort("我是2");
break;
case 3:
showShort("我是3");
break;
default:
break;
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
其中switch-case中即是你要处理的点击事件的逻辑,这里需要注意的是
if(!mTabLayout.getTabAt(position).isSelected()){
return;
}
这段代码即表示只有当前item被选中的情况下,点击事件才生效。这个方法可以用来处理TabLayout和ViewPager联动的情况下,仍需要在item上添加处理事件的情况。
点击事件效果图如下:
ok,今天关于TabLayout相关知识就讲到这里了。