importSUC 2017-09-13
使用android的design支持包中的android.support.design.widget.TabLayout结合ViewPager/Fragment来写多Tab的应用,只需要一句代码,就可以完成Tab与ViewPager切换的联动,免除很多麻烦。
mTabLayout.setupWithViewPager(mViewPager);
先写个主布局文件,只需要加入ViewPager和TabLayout即可,Tab可在ViewPager上方,也可在下方,看各自需求:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="true"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/container_viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/color_white" />
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/tabbar_def_height"
app:tabBackground="@color/color_f7f7f7"
app:tabIndicatorHeight="@dimen/margin_0"
app:tabMode="fixed" />
</LinearLayout>在java代码中,ViewPager按常规设置个PagerAdapter就有效果了,但需要和Tab关联,需要加上setupWithViewPager()的调用:
mViewPager = (ViewPager) findViewById(R.id.container_viewpager); mTabLayout = (TabLayout) findViewById(R.id.tab_layout); ... mViewPager.setAdapter(pagerAdapter); mTabLayout.setupWithViewPager(mViewPager);
如此之后发现,ViewPager可以正常使用,TabLayout的标题却没有显示,这时,如果TabLayout上只需要显示文字标题,就很容易了,在我们自定义的PagerAdapter里重写getPageTitle方法,TabLayout与ViewPager结合以后它会从这里读取内容去显示:
public class MainPagerAdapter extends FragmentPagerAdapter {
...
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
} Tab的标题显示出来了,联动也可以了,样式的话,在TabLayout控件的属性里设置就行了。什么?标题光有文字还不够?那也可以,只想在上方加个图标,弄个仿微信样式的话也不需要自定义布局文件,主要有两种办法,第一是在setupWithViewPager之后,把循环给单个Tab设置icon:
mTabLayout.setupWithViewPager(mViewPager); mTabLayout.getTabAt(0).setIcon(R.mipmap.ic_launcher); mTabLayout.getTabAt(1).setIcon(R.mipmap.ic_launcher); mTabLayout.getTabAt(2).setIcon(R.mipmap.ic_launcher);
另一种办法可以直接把Tab布局写死,使用控件android.support.design.widget.TabItem即可,形如:
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:background="@color/colorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Android"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:icon="@mipmap/ic_launcher"/>
</android.support.design.widget.TabLayout> 如此操作,效果也是可以给TabItem设置一个图标和一个文字标题。当然,如果想要定制更加复杂的TabLayout,同样是先获取Tab,给它设置自定义View即可:
mTabLayout.getTabAt(i).setCustomView(view);
自定义的完整代码如下:
首先我自定义了一个结构TabItemInfo,用于方便用代码添加Tab和ViewPager的Item,一看便明了:
public class TabItemInfo {
private Class<? extends Fragment> fragmentClass;
private int nameResource;
private int iconResource;
public TabItemInfo(Class<? extends Fragment> fragmentClass, @StringRes int nameResource,
@DrawableRes int iconResource) {
this.fragmentClass = fragmentClass;
this.nameResource = nameResource;
this.iconResource = iconResource;
}
public Class<? extends Fragment> getFragmentClass() {
return fragmentClass;
}
public int getNameResource() {
return nameResource;
}
public int getIconResource() {
return iconResource;
}
} PagerAdapter,无奇特之处,只是多加了一个根据position来获取自定义TabView的方法,以便在Activity里设置TabLayout的时候可以方便获取:
public class MainPagerAdapter extends FragmentPagerAdapter {
private Context mContext;
private List<TabItemInfo> mTabItems;
public MainPagerAdapter(Context context, FragmentManager fm, List<TabItemInfo> tabItems) {
super(fm);
mContext = context;
mTabItems = tabItems;
}
@Override
public Fragment getItem(int position) {
try {
return mTabItems.get(position).getFragmentClass().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override
public int getCount() {
return mTabItems.size();
}
public View getTabView(int position) {
TabItemInfo itemInfo = mTabItems.get(position);
View view = LayoutInflater.from(mContext).inflate(R.layout.custom_view_tab_item, null);
TextView tv = (TextView) view.findViewById(R.id.tab_text);
tv.setText(itemInfo.getNameResource());
ImageView img = (ImageView) view.findViewById(R.id.tab_image);
img.setImageResource(itemInfo.getIconResource());
return view;
}
} 在Activity里设置ViewPager和TabLayout:
mViewPager = (ViewPager) findViewById(R.id.container_viewpager);
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
List<TabItemInfo> tabItems = new LinkedList<>();
tabItems.add(new TabItemInfo(CashLoanFragment.class, R.string.cash_loan, R.drawable.apply_tab_icon_drawable));
tabItems.add(new TabItemInfo(GoodsLoanFragment.class, R.string.apply_credit, R.drawable.phone_tab_icon_drawable));
tabItems.add(new TabItemInfo(UserCenterNewFragment.class, R.string.user_center, R.drawable.my_tab_icon_drawable));
MainPagerAdapter pagerAdapter = new MainPagerAdapter(this, getSupportFragmentManager(), tabItems);
mViewPager.setAdapter(pagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
TabLayout.Tab tab = mTabLayout.getTabAt(i);
if (tab != null) {
tab.setCustomView(pagerAdapter.getTabView(i));
}
}这样之后,自定义的TabItemView就设置好了,注意,自定义的布局里,background,textColor之类的,可以用selector指定好选中状态和非选中状态的不同资源,这样TabLayout左右切换的时候,才会有效果。