简述
我们在[Android:Material Design兼容库(Design Support Library)]这篇文章已经对TabLayout有了初步的介绍,这篇文章主要介绍TabLayout和ViewPager使用。
在开始之前,我们先来看看官网文档的说明,如何与ViewPager进行联动:
You should set a listener via
setOnTabSelectedListener(OnTabSelectedListener) to be notified when
any tab’s selection state has been changed. If you’re using a
ViewPager together with this layout, you can use
setTabsFromPagerAdapter(PagerAdapter) which will populate the tabs
using the given PagerAdapter’s page titles. You should also use a
TabLayout.TabLayoutOnPageChangeListener to forward the scroll and
selection changes to this layout
恩,看起来很容易啊,简单翻译一下就是:
通过setOnTabSelectedListener设置一个监听器来响应选项卡的选择状态
可以通过setTabsFromPagerAdapter来使用PagerAdapter的page title
使用TabLayout.TabLayoutOnPageChangeListener来联动滑动
TabLayout属性
常用的属性有三个:
- app:tabSelectedTextColor:Tab被选中字体的颜色
- app:tabTextColor:Tab未被选中字体的颜色
- app:tabIndicatorColor:Tab指示器下标的颜色
TabLayout方法
- addTab(TabLayout.Tab tab, int position, boolean setSelected) 增加选项卡到 layout 中
- addTab(TabLayout.Tab tab, boolean setSelected) 同上
- addTab(TabLayout.Tab tab) 同上
- getTabAt(int index) 得到选项卡
- getTabCount() 得到选项卡的总个数
- getTabGravity() 得到 tab 的 Gravity
- getTabMode() 得到 tab 的模式
- getTabTextColors() 得到 tab 中文本的颜色
- newTab() 新建个 tab
- removeAllTabs() 移除所有的 tab
- removeTab(TabLayout.Tab tab) 移除指定的 tab
- removeTabAt(int position) 移除指定位置的 tab
- setOnTabSelectedListener(TabLayout.OnTabSelectedListener onTabSelectedListener) 为每个 tab 增加选择监听器
- setScrollPosition(int position, float positionOffset, boolean updateSelectedText) 设置滚动位置
- setTabGravity(int gravity) 设置 Gravity
- setTabMode(int mode) 设置 Mode,有两种值:TabLayout.MODE_SCROLLABLE和TabLayout.MODE_FIXED分别表示当tab的内容超过屏幕宽度是否支持横向水平滑动,第一种支持滑动,第二种不支持,默认不支持水平滑动。
- setTabTextColors(ColorStateList textColor) 设置 tab 中文本的颜色
- setTabTextColors(int normalColor, int selectedColor) 设置 tab 中文本的颜色 默认 选中
- setTabsFromPagerAdapter(PagerAdapter adapter) 设置 PagerAdapter
- setupWithViewPager(ViewPager viewPager) 和 ViewPager 联动
xml布局文件
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#FF00FF00"
app:tabSelectedTextColor="#FF00FF00"
app:tabTextColor="#FF000000"
app:tabMode="scrollable"
app:tabGravity="center"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
恩,很简单,就是一个TabLayout和一个ViewPager,并且是上下排列的。
Java类
首先我们要find这两个控件:
mTabLayout = (TabLayout) findViewById(R.id.tl);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
为了演示程序,还需要两个伪数据来充当ViewPager的内容和title
private String[] mTitle = new String[20];
private String[] mData = new String[20];
{
for(int i=0;i<20;i++) {
mTitle[i] = "title" + i;
mData[i] = "data" + i;
}
}
下面,我们将要按照上面的步骤,一点点来撸代码啦:
第一步,设置TabLayout的选项卡监听:
mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
当我们的tab选择时,让viewpager选中对应的item。
第二步,设置Tab的标题来自PagerAdapter.getPageTitle()。
mTabLayout.setTabsFromPagerAdapter(mAdapter);
第三步,设置TabLayout.TabLayoutOnPageChangeListener,给谁设置呢?当然是ViewPager了,怎么设置呢?
final TabLayout.TabLayoutOnPageChangeListener listener =
new TabLayout.TabLayoutOnPageChangeListener(mTabLayout);
mViewPager.addOnPageChangeListener(listener);
哦,原来TabLaout.TabLayoutOnPageChangeLisetener继承自OnPageChangeListener,不行来看:
public static class TabLayoutOnPageChangeListener implements OnPageChangeListener {...}
注意,这里是addOnPageChangeListener,也就是说,你还可以add N个Listener而不会被覆盖掉。
到这里,步骤我们都走完了,但是别忘了给ViewPage设置Adapter。
mViewPager.setAdapter(mAdapter);
最后是Adapter的代码:
private PagerAdapter mAdapter = new PagerAdapter() {
@Override
public CharSequence getPageTitle(int position) {
return mTitle[position];
}
@Override
public int getCount() {
return mData.length;
}
@Override
public Object instantiateItem(View container, int position) {
TextView tv = new TextView(MainActivity.this);
tv.setTextSize(30.f);
tv.setText(mData[position]);
((ViewPager) container).addView(tv);
return tv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
};
运行一下代码,看看效果:
是不是很简单? 几行代码就搞定了这种效果,当然,你也可以选择自己重写View的方式实现,可以参考另一篇博客《打造史上最容易使用的Tab指示符——Indicator》。
…
如果,你感觉这就简单,那你也太容易满足啦,Google还给我们提供了一个方法,将这些步骤封装到一块,让我们开发者可以一步搞定。public void setupWithViewPager (ViewPager viewPager),继续看看文档的说明:
The one-stop shop for setting up this TabLayout with a ViewPager.
This method will:
Add a ViewPager.OnPageChangeListener that will forward events to this
TabLayout. Populate the TabLayout’s tabs from the ViewPager’s
PagerAdapter. Set our TabLayout.OnTabSelectedListener which will
forward selected events to the ViewPager
大体解释一下就是:
这个方法是addOnPageChangeListener和setOnTabSelectedListener的封装。
所以我们注释掉对应代码,替换成setupWithViewPager。
mTabLayout.setTabsFromPagerAdapter(mAdapter);
TabLayout.TabLayoutOnPageChangeListener(mTabLayout);
mViewPager.setAdapter(mAdapter);
mTabLayout.setupWithViewPager(mViewPager);
效果还是上面的效果,但是代码量明显少了,仅需两行代码搞定。
但是需要注意一下,setupWithViePager必须在ViewPager.setAdapter()之后调用!为什么呢?来源码找答案:
public void setupWithViewPager(ViewPager viewPager) {
PagerAdapter adapter = viewPager.getAdapter();
if(adapter == null) {
throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
} else {
...
}
}
首先去获取该ViewPager上的Adapter,如果没有Adapter,则抛出一个异常!
好了,到现在TabLayout和ViewPager一块使用的用法就讲解完了,相信还是非常简单的,仅仅两行代码就可以搞定。