Android指示器_TabLayout详解

TabLayout是属于容器控件, 提供水平显示Tab的效果. 常常和ViewPager配合使用. 我将全面地讲解其用法. 反正我是没看过比我还详细的了. 该文章可以当做笔记来查询. 有疑惑或者补充希望能评论, 虽然我也不一定会知道答案.

演示

添加依赖

这是Android Design 包下的类, 该包是Android5.0引入的UI包

1
compile 'com.android.support:design:25.2.0'

布局

1
2
3
4
5
6
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.design.widget.TabLayout>

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tab_layout)
TabLayout mTabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mTabLayout.addTab(mTabLayout.newTab().setText("首页"));
mTabLayout.addTab(mTabLayout.newTab().setText("分类"));
mTabLayout.addTab(mTabLayout.newTab().setText("设置"));
}
}

第二种方式

完全通过布局创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="首页"
/>
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分类"
/>
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="设置"
/>
</android.support.design.widget.TabLayout>

TabLayout

方法有点多

属性

修改布局的属性

显示模式

可滑动

1
app:tabMode="scrollable"

固定

1
app:tabMode="fixed"

指示器选项

1
2
app:tabIndicatorHeight="10dp" //指示器高度
app:tabIndicatorColor="@color/colorPrimary" // 指示器颜色

文字选项

1
2
3
app:tabSelectedTextColor="#ffffff" // 选择的Tab的文字颜色
app:tabTextColor="#000000" // 未选择的Tab文字颜色
app:tabTextAppearance="@style/Base.TextAppearance.AppCompat.Large" // 文字样式

背景设置

两者没什么区别

1
2
android:background="@color/colorAccent" // 背景
app:tabBackground="@color/colorPrimary" //背景

标签距离

1
2
3
4
5
app:tabPaddingStart="10dp"
app:tabPaddingBottom="10dp"
app:tabPadding="10dp"
app:tabPaddingEnd="10dp"
app:tabPaddingTop="10dp"

对齐方式

居中显示

1
app:tabGravity="center"

填充

1
app:tabGravity="fill"

偏移

从左边开始偏移距离, 必须是可滑动的模式scrollable

1
app:tabContentStart="200dp"

标签宽度限制

最大宽度

1
app:tabMaxWidth="50dp"

最小宽度

1
app:tabMinWidth="100dp"

代码

TabLayout提供的方法

标签

创建标签

1
TabLayout.Tab newTab ()

添加标签, 只有添加后才能显示

1
2
3
4
5
6
7
8
9
10
11
void addTab (TabLayout.Tab tab)
void addTab (TabLayout.Tab tab,
int position)
void addTab (TabLayout.Tab tab,
boolean setSelected)
void addTab (TabLayout.Tab tab,
int position,
boolean setSelected)

删除标签

1
void removeTab (TabLayout.Tab tab)

通过索引删除标签

1
void removeTabAt (int position)

删除全部标签

1
void removeAllTabs ()

得到标签

1
TabLayout.Tab getTabAt (int index)

得到标签总数

1
int getTabCount ()

设置样式

指示器
1
2
void setSelectedTabIndicatorColor (int color) // 指示器颜色
void setSelectedTabIndicatorHeight (int height) // 指示器高度
标签文本
1
2
3
4
void setTabTextColors (int normalColor, // 正常颜色
int selectedColor) // 选择状态颜色
void setTabTextColors (ColorStateList textColor) // 状态颜色

显示模式

这个之前属性里面介绍过了

1
2
int getTabMode ()
void setTabMode (int mode)

mode:

  1. MODE_SCROLLABLE
  2. MODE_FIXED

对齐方式

1
2
void setTabGravity (int gravity)
int getTabGravity ()

添加View

不止是添加标签Tab还可以直接添加View

1
2
3
4
5
6
7
8
9
10
11
void addView (View child)
void addView (View child,
int index)
void addView (View child,
ViewGroup.LayoutParams params)
void addView (View child, // View对象
int index, // 位置索引
ViewGroup.LayoutParams params) // 布局参数
得到当前选择的位置
1
int getSelectedTabPosition ()

选择监听器

该方法已经被废弃, 不推荐使用.

1
void setOnTabSelectedListener (TabLayout.OnTabSelectedListener listener)

替代的方法是

1
void addOnTabSelectedListener (TabLayout.OnTabSelectedListener listener)

该监听器用完后需要删除

1
void removeOnTabSelectedListener (TabLayout.OnTabSelectedListener listener)

一次性删除所有添加的选择监听器

1
void clearOnTabSelectedListeners ()

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class MainTabSelectListener implements TabLayout.OnTabSelectedListener {
@Override
public void onTabSelected(TabLayout.Tab tab) {
// Tab被选择
switch (tab.getPosition()) { // 我在这里处理选择不同的Tab触发不同事件
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
// Tab被取消选择
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// Tab被重新选择
}
}

Tab

该类是TabLayout的内部类, 表示TabLayout中的每一个标签. 我将介绍这个类的所有方法

判断是否被选择

1
boolean isSelected ()

设置为被选择状态

1
void select ()

描述内容

如果你没用设置描述内容, 默认的是标签的标题

1
2
3
TabLayout.Tab setContentDescription (int resId) // 用strings id的
TabLayout.Tab setContentDescription (CharSequence contentDesc)
CharSequence getContentDescription ()

自定义标签的内容

每个标签可以尽情的自定义视图

1
2
TabLayout.Tab setCustomView (int resId)
TabLayout.Tab setCustomView (View view)

标签的标签

给Tab设置tag, 然后就可以通过tag得到Tab

1
2
TabLayout.Tab setTag (Object tag)
Object getTag ()

添加图标

1
2
3
TabLayout.Tab setIcon (Drawable icon)
TabLayout.Tab setIcon (int resId)
Drawable getIcon ()

标题的文字

1
2
3
TabLayout.Tab setText (int resId)
TabLayout.Tab setText (CharSequence text)
CharSequence getText ()

当前标签位置

1
int getPosition ()

关联ViewPager

TabLayout和ViewPager配合使用是最常见的运用方式, 可以说量身打造. 这里我将介绍两种方式.

两者配合使用后TabLayout就不能通过自己创建Tab了, 需要PagerAdapter中实现getPagerTitle()方法返回标签的文字. 标签的数量有ViewPager的分页数量决定.

布局中嵌套

布局

1
2
3
4
5
6
7
8
9
10
11
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tab_layout)
TabLayout mTabLayout;
@BindView(R.id.viewpager)
ViewPager mViewpager;
private ArrayList<View> mList;
private String[] mTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initData();
mViewpager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return mList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = mList.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public CharSequence getPageTitle(int position) {
return mTitle[position];
}
});
}
private void initData() {
View viewpagerA = getLayoutInflater().inflate(R.layout.viewpager_a, null);
View viewpagerB = getLayoutInflater().inflate(R.layout.viewpager_b, null);
View viewpagerC = getLayoutInflater().inflate(R.layout.viewpager_c, null);
mList = new ArrayList<>();
mList.add(viewpagerA);
mList.add(viewpagerB);
mList.add(viewpagerC);
mTitle = new String[]{"首页", "分类", "设置"};
}

代码中关联

如果布局没有嵌套

1
2
3
4
5
6
7
8
9
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
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="match_parent"/>

就需要在ViewPager设置PagerAdapter之前关联两者

1
mTabLayout.setupWithViewPager(mViewpager);

虽然配合ViewPager后TabLayout创建的Tab并不能正常显示, 因为setupWithViewPager内部方法是先删除所有的标签再添加.

但是还是可以通过getTabAt()得到标签之后进行修改.