标签布局TabLayout是MaterialDesign库中的一个新控件,常与工具栏Toolbar搭配使用。大家平时常用的App就有不少采用了TabLayout,比如京东App的商品页,从左到右依次是“商品”、“详情”、“评价”,具体界面如下图所示:
京东的这个页面便是典型的Toolbar+TabLayout效果,实现的话不外乎Toolbar内部嵌套TabLayout,然后TabLayout再通过ViewPager集成多个Fragment页。如此说来其实也不复杂,那还是先看看模拟京东的页面效果图。下面是模拟页面之一的“商品”页:
下面是模拟页面之一的“详情”页:
接下来看看这两个页面互相切换的动图,切换操作可以通过点击顶部的标签文字实现(TabLayout切换页面),也可以通过在下方左右滑动页面实现(ViewPager切换页面)。如下所示:
看完了效果图,再来分析分析具体的实现过程。TabLayout的展现形式类似PagerTabStrip,一样是文字标签带下划线,不同的是,TabLayout允许定制更丰富的样式,它新增的样式属性主要有:
tabBackground : 指定标签的背景。
tabIndicatorColor : 指定下划线的颜色。
tabIndicatorHeight : 指定下划线的高度。
tabTextColor : 指定标签文字的颜色。
tabTextAppearance : 指定标签文字的风格。
tabSelectedTextColor : 指定选中文字的颜色。
而在代码中,TabLayout通过如下方法操作标签:
newTab : 创建新标签。
addTab : 添加一个标签。
getTabAt : 获取指定位置的标签。
setOnTabSelectedListener : 设置标签的选中监听器。该监听器需实现OnTabSelectedListener接口的三个方法,具体说明如下:
onTabSelected: 在标签选中时触发;
onTabUnselected: 在标签取消选中时触发;
onTabReselected: 在标签已选中状态再次选中时触发;
上面的属性和方法说明略显单调,那还是给个具体的代码例子,看看这些属性和方法该如何搭配使用。下面是界面布局的xml文件例子:
下面是操纵TabLayout和ViewPager的代码片段:
public class TabLayoutActivity extends AppCompatActivity implements
OnTabSelectedListener, OnPageChangeListener {
private Toolbar tl_head;
private ViewPager vp_content;
private TabLayout tab_title;
private ArrayList mTitleArray = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_layout);
tl_head = (Toolbar) findViewById(R.id.tl_head);
tab_title = (TabLayout) findViewById(R.id.tab_title);
vp_content = (ViewPager) findViewById(R.id.vp_content);
setSupportActionBar(tl_head);
tl_head.setNavigationOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
mTitleArray.add("商品");
mTitleArray.add("详情");
initTabLayout();
initTabViewPager();
}
private void initTabLayout() {
tab_title.addTab(tab_title.newTab().setText(mTitleArray.get(0)));
tab_title.addTab(tab_title.newTab().setText(mTitleArray.get(1)));
tab_title.setOnTabSelectedListener(this);
}
private void initTabViewPager() {
GoodsPagerAdapter adapter = new GoodsPagerAdapter(
getSupportFragmentManager(), mTitleArray);
vp_content.setAdapter(adapter);
vp_content.addOnPageChangeListener(this);
}
@Override
public void onTabReselected(Tab tab) {
}
@Override
public void onTabSelected(Tab tab) {
vp_content.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(Tab tab) {
}
@Override
public void onPageScrollStateChanged(int position) {
}
@Override
public void onPageScrolled(int position, float arg1, int arg2) {
}
@Override
public void onPageSelected(int position) {
tab_title.getTabAt(position).select();
}
}
以上的xml文件与代码配合,已经能够实现文章开头的商品页切换效果了。不过这里尚存在两点待改进的地方,首先我们看到,商品页和详情页之间的切换,既能通过点击TabLayout实现,也能通过滑动ViewPager实现;也就是说,TabLayout和ViewPager要完成的页面切换其实是同一个行为,可是代码中给TabLayout注册了一个选择监听器,得重写三个方法;同样的,ViewPager也注册了一个滑动监听器,又得重写三个方法;如此一来,一共要重写六个方法,使得代码的冗余程度增加了。
当然Android在设计之初也考虑到了这个冗余的情况,所以这个页面切换其实有捷径可以走。比如对于ViewPager的页面切换,多数情况只需重写onPageSelected一个方法,所以系统已经自带了简单的滑动监听器SimpleOnPageChangeListener,使用该监听器即可大大简化代码,简化后的页面切换代码如下所示:
vp_content.addOnPageChangeListener(new SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
tab_title.getTabAt(position).select();
}
});
对于TabLayout的页面切换,它的简化方案更简洁,只需下面一行代码,即可完成TabLayout与ViewPager的页面选择关联,具体代码如下所示:
tab_title.setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(vp_content));
TabLayout第二个有待改进的地方,是它的标签文字风格。前面说到,TabLayout的几个属性可以调整标签文字的颜色、样式等等,可是这仅限于修改文本,无法在标签中定制图片,因此若要给标签加个角标什么的,就必须进行自定义了。虽然TabLayout默认采用文本标签,但它也支持自定义标签,而且自定义标签的过程也很简单,只要定义标签项的布局文件,然后调用Tab页的setCustomView方法即可设置自定义布局。
比如下面是一个标签项的自定义布局文件,其中指定了一个标签文本,加上一个圆点角标,并通过状态图形区分标签的选中与非选中两种状态:
接着打开活动页面代码,只消把initTabLayout函数改成下面这样,寥寥几行就实现了自定义的标签栏:
private void initTabLayout() {
tab_title.addTab(tab_title.newTab().setCustomView(R.layout.item_toolbar1));
tv_toolbar1 = (TextView) findViewById(R.id.tv_toolbar1);
tv_toolbar1.setText(mTitleArray.get(0));
tab_title.addTab(tab_title.newTab().setCustomView(R.layout.item_toolbar2));
tv_toolbar2 = (TextView) findViewById(R.id.tv_toolbar2);
tv_toolbar2.setText(mTitleArray.get(1));
tab_title.setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(vp_content));
}
自定义标签栏的最终页面切换效果如下面的动图所示:
点此查看Android开发笔记的完整目录
__________________________________________________________________________
本文现已同步发布到微信公众号“老欧说安卓”,打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。