以前看慕课网的教程,写过一个微信Tab选项卡切换的例子,使用的是ViewPager+Fragment来实现的,说实话,当时为了实现一些效果,还是写了蛮多的代码,但是,今天介绍的TabLayout+ViewPager+Fragment实现导航栏可以使用很少的代码实现很棒的效果。
首先说说TabLayout,它是在Android5.0之后提出的,可以实现Material Design效果,可以方便地帮助我们实现导航栏的效果。接着说一下ViewPager,它是Android扩展包v4中的类,可以实现view的左右切换。Fragment就不过多介绍了,相信大家都了解。下面就说说具体的实现步骤:
一、实现顶部导航栏
1 . 添加所需依赖
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
说明:上面的第一个包我们在创建Android工程的时候一般会默认引入,他其中包含了Android support v4的包,我们此处是使用v4包中的ViewPager。下面的那个包是我们要使用其中的TabLayout。
2 . 创建对应于每个Tab选项卡的Fragment
接着我们创建对应于每个Tab的View页面,假设你需要3个Tab,则对应创建3个Fragment文件,并生成每个Fragment对应的布局文件。此处写一个作为示例。
Fragment1.java
public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment1,container, false);
}
}
fragment1.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
RelativeLayout>
3 . 定义适配器
接着我们要开始定义适配器类,为下一步的绑定做准备。
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private String[] mTitles = new String[]{"Fragment1", "Fragment2"};
public HomeFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
//此处根据不同的position返回不同的Fragment
if (position == 1){
return new Fragment2();
}
return new Fragment1();
}
@Override
public int getCount() {
//此处返回Tab的数目
return mTitles.length;
}
@Override
public CharSequence getPageTitle(int position) {
//此处返回每个Tab的title
return mTitles[position];
}
}
上面的代码很好理解,这里不再解释。
4 . 创建主布局文件
由于我们要实现的是顶部导航栏,所有我们此处的布局应该为上面部分是TabLayout,下面部分是ViewPager,布局文件如下:
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_role"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorGray">
.support.design.widget.TabLayout
app:tabGravity="fill"
android:id="@+id/home_tablayout"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@color/colorWhite"
app:tabIndicatorColor="#66ff33"
app:tabIndicatorHeight="2dp"
app:tabTextColor="@color/colorTheme"
app:tabSelectedTextColor="#CC33FF"
app:tabMode="fixed"
app:tabBackground="@drawable/tablayout_selector"
app:tabTextAppearance="@style/TabLayoutTextAppearance">
.support.design.widget.TabLayout>
.support.v4.view.ViewPager
android:id="@+id/home_viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
.support.v4.view.ViewPager>
上面ViewPager的使用没什么好说的,主要是说说TabLayout的一些属性:
属性 | 作用 |
---|---|
tabGravity | fill 多个tab会平分TabLayout来显示 / center 多个tab会按实际大小在TabLayout上居中显示 |
tabIndicatorColor | tab上面指示器的颜色 |
tabIndicatorHeight | tab上面指示器的高度 |
tabTextColor | tab上面显示的字体的颜色 |
tabSelectedTextColor | tab被选中时字体的颜色 |
tabMode | fixed TabLayout上多个tab是固定的 / scrollable 多个tab时,tab是可以滚动的 |
注意:这是我踩过的一个坑,当时我把 tabMode设置为scrollable,然后发现tabGravity设置为fill,可是tab还是不能平分TabL,后来才知道,只有tabMode设置为fixed时,tabGravity设置为fill才会生效。
上面的tabBackground我是使用自定义的一个selector实现tab在选中和未选中状态的背景颜色,下面是代码
tablayout_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="@color/colorTheme"/>
<item android:drawable="@color/colorGray"/>
selector>
tabTextAppearance属性是自己简单定义的一个文本样式,主要是设置字体大小及颜色,下面是代码:
style.xml文件
5 . 在MainActivity中绑定布局
private TabLayout mTabLayout;
private ViewPager mViewPager;
private MyFragmentPagerAdapter mFragmentPagerAdapter;
private TabLayout.Tab mTab1;
private TabLayout.Tab mTab2;
mViewPager = (ViewPager) findViewById(R.id.m_viewpager);
mFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
//给ViewPager设置适配器
mViewPager.setAdapter(mFragmentPagerAdapter);
//tablayout与Viewpager绑定
mTabLayout = (TabLayout) findViewById(R.id.m_tablayout);
mTabLayout.setupWithViewPager(mViewPager);
mTab1 = mTabLayout.getTabAt(0);
mTab = mTabLayout.getTabAt(1);
通过上面的设置,就可以实现顶部导航栏啦。
下面放上一个效果图:
其实,底部导航栏非常好实现,我们只需要在布局文件中,将上面的部分放置ViewPager,下面的部分放置TabLayout即可,其他内容不变。或许我们有时候需要在底部导航栏加入小图标,那我们就可以在上面的基础上通过以下代码进行设置:
mTab1.setIcon(R.drawable.ic_1);
mTab2.setIcon(R.drawable.ic_2);
有时候我们可能并不希望我们的ViewPager是可滑动切换的,只希望它可以点击切换,那我们可以通过自定义ViewPager,同时让其不再拦截触摸事件即可,代码如下:
public class DisabledTouchViewPager extends ViewPager {
//true为允许滑动手势
private boolean enable = false;
public DisabledTouchViewPager(Context context) {
super(context);
}
public DisabledTouchViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return enable;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return enable;
}
}
然后将xml文件中的ViewPager换成我们自定义的ViewPager即可。记得必须使用自定义ViewPager的完整路径。