以前要实现Android选项卡视图,基本上使用的是TabHost,不过谷歌已经不推荐使用了。现在比较普遍的是采用TabLayout实现选项卡布局。
布局
首先,在你的布局文件里,添加一个TabLayout布局
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
>
<android.support.design.widget.TabLayout
android:id="@+id/tab"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</android.support.design.widget.TabLayout>
</LinearLayout>
然后在onCreate的时候,给它添加两个tab
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = (TabLayout)findViewById(R.id.tab);
TabLayout.Tab tab1 = tabLayout.newTab().setText("tab111");
TabLayout.Tab tab2 = tabLayout.newTab().setText("tab222");
tabLayout.addTab(tab1);
tabLayout.addTab(tab2);
}
此时的效果是这样的。只有两个选项卡,卡的标题不同,点击的时候才能切换,里面没什么内容。
现在只是有两个tab,但是tab里没有内容。
tab.setCustomView()只是用来设置tab标签的自定义视图,而不是tab所代表的内容视图。
tab.setCustomView如果放在tablayout.addTab之前执行,那么会报错。
监听tab切换
在onCreate里面继续添加以下代码,给tablayout添加上切换监听
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
Log.d(this.getClass().toString(), "tab;selected;position=" + tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
Log.d(this.getClass().toString(), "tab;unselected;position=" + tab.getPosition());
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
Log.d(this.getClass().toString(), "tab;released;position=" + tab.getPosition());
}
});
在onTabSelected里面,根据position就可以知道点击的是第几个选项卡,从而做出相应的响应。一开始创建的时候并不会触发上面这三个函数中的任何一个,而是当有切换动作的时候,才会触发。
此时的切换,还只能是点击切换。如果要使用滑动切换,就要用到viewpager
滑动切换
在布局文件里添加viewpager,最后布局文件变成下面这个样子
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
>
<android.support.design.widget.TabLayout
android:id="@+id/tab"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout>
要将viewpager绑定在tablayout上。由viewpager来绑定两个fragment
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sendback);
Log.d(this.getClass().toString(), "-------onCreate---------");
tabLayout = (TabLayout)findViewById(R.id.tab_needSend);
viewPager = (ViewPager)findViewById(R.id.viewpager);
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragment(new FragmentOne(), "tab one";
viewPagerAdapter.addFragment(new FragmentTwo(), "tab two");
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
viewPager.setCurrentItem(position);//如果不添加此句,则点击的时候视图不会切换
Log.d(this.getClass().toString(), "tab;selected;position=" + tab.getPosition());
if (0 == position) {
FragmentOne fragment = (FragmentOne)viewPagerAdapter.getItem(position);
fragment.refreshData();//刷新数据
}else{
FragmentTwo fragment = (FragmentTwo)viewPagerAdapter.getItem(position);
fragment.refreshData();
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
Log.d(this.getClass().toString(), "tab;unselected;position=" + tab.getPosition());
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
Log.d(this.getClass().toString(), "tab;released;position=" + tab.getPosition());
}
});
}
这样就实现了即能点击切换,又能滑动切换。切换的时候还会刷新数据。
类似于这种TabLayout里面有多个Fragment的布局形式,假如在Fragment的布局文件里定义了一个Button,并给它写上属性android:onClick=“btClicked”
,那么运行的时候,程序会去Fragment所在的Activity里去找有没有public void btClicked(View v)
这个方法。
而我之前只是在Fragment本身的类方法里面实现了btClicked方法,所以程序每次都会崩掉,说在Activity里面找不到相应的方法。
这种问题的解决方法有两种:
1.在Fragment布局文件里依旧使用Button的android:onClick
属性,然后在Activity里面定义相关方法,然后根据view的id或者tag来做区分,做出相应的响应。
2.在Fragment布局文件里去处Button的android:onClick
属性,然后在Fragment类里面对button设置监听。
我倾向于第二种方法,毕竟属于这个Fragment的事情还是发生在这个Fragment类里面比较好。
修改tab颜色
修改选中条的颜色
tabLayout.setSelectedTabIndicatorColor
修改选中和不选中时tab字体的颜色
tabLayout.setTabTextColors
源代码中对setTabTextColors的解释: