大多数应用程序都会在底部使用3~5个Tab对应用程序的主要功能进行划分,对于一些信息量非常大的应用程序,还需要在每个Tab下继续划分子Tab对信息进行分类显示.

本文实现采用FragmentTabHost+TabLayout+ViewPager实现双层嵌套Tab,实现原理如下:

第一层Tab:FragmentTabHost + Fragment;

第二层Tab:在第一层的Fragment中使用TabLayout和ViewPager实现.

第一层Tab实现:

1.布局文件activity_main.xml如下:

 <?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost android:id="@android:id/tabhost"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/> <TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"/>
</LinearLayout> </android.support.v4.app.FragmentTabHost>

说明:其中FrameLayout用于显示内容,TabWidget用于显示标签。

2.底部Tab布局:view_tab_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"> <ImageView
android:id="@+id/tab_iv_image"
android:layout_width="26dp"
android:layout_height="26dp"
android:contentDescription="@null"/> <TextView
android:id="@+id/tab_tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:textColor="#ff847d7b"
android:textSize="12sp"/> </LinearLayout>

底部Tab由一张图片和tab名称组成。

3.在mainActivity.java中定义一个内部类TabItem,用于表示底部tab:

     class TabItem {
//正常情况下显示的图片
private int imageNormal;
//选中情况下显示的图片
private int imagePress;
//tab的名字
private int title;
private String titleString; //tab对应的fragment
public Class<? extends Fragment> fragmentClass; public View view;
public ImageView imageView;
public TextView textView; public TabItem(int imageNormal, int imagePress, int title,Class<? extends Fragment> fragmentClass) {
this.imageNormal = imageNormal;
this.imagePress = imagePress;
this.title = title;
this.fragmentClass =fragmentClass;
} public Class<? extends Fragment> getFragmentClass() {
return fragmentClass;
}
public int getImageNormal() {
return imageNormal;
} public int getImagePress() {
return imagePress;
} public int getTitle() {
return title;
} public String getTitleString() {
if (title == 0) {
return "";
}
if(TextUtils.isEmpty(titleString)) {
titleString = getString(title);
}
return titleString;
} public View getView() {
if(this.view == null) {
this.view = getLayoutInflater().inflate(R.layout.view_tab_indicator, null);
this.imageView = (ImageView) this.view.findViewById(R.id.tab_iv_image);
this.textView = (TextView) this.view.findViewById(R.id.tab_tv_text);
if(this.title == 0) {
this.textView.setVisibility(View.GONE);
} else {
this.textView.setVisibility(View.VISIBLE);
this.textView.setText(getTitleString());
}
this.imageView.setImageResource(imageNormal);
}
return this.view;
} //切换tab的方法
public void setChecked(boolean isChecked) {
if(imageView != null) {
if(isChecked) {
imageView.setImageResource(imagePress);
}else {
imageView.setImageResource(imageNormal);
}
}
if(textView != null && title != 0) {
if(isChecked) {
textView.setTextColor(getResources().getColor(R.color.main_botton_text_select));
} else {
textView.setTextColor(getResources().getColor(R.color.main_bottom_text_normal));
}
}
}
}

4.初始化Tab数据:

     //初始化Tab数据
private void initTabData() {
mTableItemList = new ArrayList<>();
//添加tab
mTableItemList.add(new TabItem(R.drawable.main_bottom_home_normal,R.drawable.main_bottom_home_press,R.string.main_home_text, TestFragment1.class));
mTableItemList.add(new TabItem(R.drawable.main_bottom_attention_normal,R.drawable.main_bottom_attention_press,R.string.main_attention_text, TestFragment2.class));
mTableItemList.add(new TabItem(R.drawable.main_bottom_mine_normal,R.drawable.main_bottom_mine_press,R.string.main_mine_text, TestFragment3.class)); }

5.初始化选项卡视图:

 //初始化主页选项卡视图
private void initTabHost() {
//实例化FragmentTabHost对象
FragmentTabHost fragmentTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
fragmentTabHost.setup(this,getSupportFragmentManager(),android.R.id.tabcontent); //去掉分割线
fragmentTabHost.getTabWidget().setDividerDrawable(null); for (int i = 0; i<mTableItemList.size(); i++) {
TabItem tabItem = mTableItemList.get(i);
//实例化一个TabSpec,设置tab的名称和视图
TabHost.TabSpec tabSpec = fragmentTabHost.newTabSpec(tabItem.getTitleString()).setIndicator(tabItem.getView());
fragmentTabHost.addTab(tabSpec,tabItem.getFragmentClass(),null); //给Tab按钮设置背景
fragmentTabHost.getTabWidget().getChildAt(i).setBackgroundColor(getResources().getColor(R.color.main_bottom_bg)); //默认选中第一个tab
if(i == 0) {
tabItem.setChecked(true);
}
} fragmentTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
@Override
public void onTabChanged(String tabId) {
//重置Tab样式
for (int i = 0; i< mTableItemList.size(); i++) {
TabItem tabitem = mTableItemList.get(i);
if (tabId.equals(tabitem.getTitleString())) {
tabitem.setChecked(true);
}else {
tabitem.setChecked(false);
}
}
}
});
}

6.在oncreate()中调用以上两个方法:

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTabData();
initTabHost();
}

至此,第一层tab实现完成,效果如下图所示:

第二层Tab实现:

第二层的tab基于第一层中的Fragment实现,本文使用了TabLayout和ViewPager。

注意:在使用TabLayout之前需要添加依赖包,例如在build.gradle中添加compile 'com.android.support:design:23.3.0'。

1.第二层tab的布局文件:

 <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:clickable="true"
android:orientation="vertical"> <android.support.design.widget.TabLayout
android:id="@+id/tab_essence"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/essence_tab_bg"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/essence_tab_text_color_press"
app:tabTextColor="@color/essence_tab_text_color_normal"
app:tabIndicatorColor="@color/essence_tab_text_color_press"/> <android.support.v4.view.ViewPager
android:id="@+id/vp_essence"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </LinearLayout>

其中TabLayout用于显示子tab,VierPager用于显示子tab对应的内容。

2.在strings.xml中配置标签数据:

     <array name="home_video_tab">
<item>全部@dream@0</item>
<item>视频@dream@1</item>
<item>声音@dream@2</item>
<item>图片@dream@3</item>
<item>段子@dream@4</item>
<item>广告@dream@5</item>
<item>剧情@dream@6</item>
</array>

3.定义显示在ViewPager中的Fragment:

 public class ContentFragment extends Fragment {

     private View viewContent;
private int mType = 0;
private String mTitle; public void setType(int mType) {
this.mType = mType;
} public void setTitle(String mTitle) {
this.mTitle = mTitle;
} @Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//布局文件中只有一个居中的TextView
viewContent = inflater.inflate(R.layout.fragment_content,container,false);
TextView textView = (TextView) viewContent.findViewById(R.id.tv_content);
textView.setText(this.mTitle); return viewContent;
} }

4.定义ViewPager的adapter:

 //继承FragmentStatePagerAdapter
public class TestFragmentAdapter extends FragmentStatePagerAdapter { public static final String TAB_TAG = "@dream@"; private List<String> mTitles; public TestFragmentAdapter(FragmentManager fm, List<String> titles) {
super(fm);
mTitles = titles;
} @Override
public android.support.v4.app.Fragment getItem(int position) {
//初始化Fragment数据
ContentFragment fragment = new ContentFragment();
String[] title = mTitles.get(position).split(TAB_TAG);
fragment.setType(Integer.parseInt(title[1]));
fragment.setTitle(title[0]);
return fragment;
} @Override
public int getCount() {
return mTitles.size();
} @Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position).split(TAB_TAG)[0];
}
}

5.Fragment具体实现:

 public class TestFragment1 extends android.support.v4.app.Fragment{

     private View viewContent;
private TabLayout tab_essence;
private ViewPager vp_essence; @Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
viewContent = inflater.inflate(R.layout.fragment_test_1,container,false);
initConentView(viewContent);
initData(); return viewContent;
} public void initConentView(View viewContent) {
this.tab_essence = (TabLayout) viewContent.findViewById(R.id.tab_essence);
this.vp_essence = (ViewPager) viewContent.findViewById(R.id.vp_essence);
} public void initData() {
//获取标签数据
String[] titles = getResources().getStringArray(R.array.home_video_tab); //创建一个viewpager的adapter
TestFragmentAdapter adapter = new TestFragmentAdapter(getFragmentManager(), Arrays.asList(titles));
this.vp_essence.setAdapter(adapter); //将TabLayout和ViewPager关联起来
this.tab_essence.setupWithViewPager(this.vp_essence);
}
}

至此,第二层tab实现完成,效果如下:

总结:

1.本文实现的双层嵌套Tab使用到了FragmentTabHost,Fragment,ViewPager和TabLayout.

2.内外层的实现是解耦的,外层实现使用的是FragmentTabHost+Fragment,内层的实现是对外层Fragment的扩展,实现方式是使用TabLayout+VierPager。

使用FragmentTabHost+TabLayout+ViewPager实现双层嵌套Tab的更多相关文章

  1. android 解决ViewPager双层嵌套的滑动问题

    解决ViewPager双层嵌套的滑动问题 今天我分享一下ViewPager的双层嵌套时影响内部ViewPager的触摸滑动问题 之前在做自己的一个项目的时候,遇到广告栏图片动态切换,我第一时间想到的就 ...

  2. 浅谈TabLayout(ViewPager+Tab联动)

    google发布了的Android Support Design库中提供了TabLayout 通过TabLayout+ViewPager实现导航栏效果,点击Tab ,ViewPager跟随变化,滑动V ...

  3. TabLayoutViewPagerDemo【TabLayout+ViewPager可滑动】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用TabLayout搭配ViewPager实现可滑动的顶部选项卡效果. 效果图 代码分析 1.演示常规的设置. 2.通过自定义Vi ...

  4. TabLayout + ViewPager

    一.实现思路 1.在build.gradle中添加依赖,例如: compile 'com.android.support:support-v4:23.4.0'compile 'com.android. ...

  5. 介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView

    本文主要介绍如下三个Android支持库控件的配合使用: TabLayout:android.support.design.widget.TabLayout ViewPager:android.sup ...

  6. [置顶] xamarin Tablayout+Viewpager+Fragment顶部导航栏

    最近几天不忙,所以把项目中的顶部导航栏的实现归集一下.android中使用TabLayout+ViewPager+Fragment制作顶部导航非常常见,代码实现也比较简单.当然我这个导航栏是基于xam ...

  7. Android开发之漫漫长途 Fragment番外篇——TabLayout+ViewPager+Fragment

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  8. TabLayout:另一种Tab的实现方式

    http://blog.csdn.NET/aigestudio/article/details/47155769 在5.0以前我们想要实现像网易新闻客户端那样的的Tab可以有很多种选择: 比如古老的T ...

  9. 安卓TabLayout+ViewPager实现切页

    安卓使用TabLayout+ViewPager+Fragment 实现页面切换,可实现左右滑动切换视图界面和点击切换 可自定义菜单栏是在顶部还是在底部 一.实现效果: 二.实现过程: 2.1 一些重要 ...

随机推荐

  1. xUnit安装及注意事项

    前言 对于单元测试,想必大家都已再熟悉不过了,同时单元测试的重要性也越发突出,在招聘中也特别强调单元测试,但是对于微软内置的单元测试还是太过于繁琐,于是都在寻找一种简洁并且更加轻量的测试工具.用的最多 ...

  2. js 根据屏幕大小调用不同的css文件

    原因:屏幕大小不一样,网站看起来总觉得怪怪的,所以,针对不同大小的屏幕,写了不同的css,写完了,要解决的问题就是:怎么根据屏幕的大小来引用不同的CSS,下面就是解决方法了. 解决方法:首先,在hea ...

  3. 深入理解 OWIN 中的 Host 和 Server

    The Open Web Interface for .NET (OWIN),注意单词为大写,之前好像都写成了 Owin,但用于项目的时候,可以写成:Microsoft.Owin.*. OWIN 体系 ...

  4. 恢复SharePoint Server 2013 中的“新颖快建视图”

    初始化后就很漂亮的"新颖快建视图" 在配置好了OWA(Office Web Apps)的环境下,可以使用独特的"新颖快建视图"新建文件与文件夹,如下图所示: F ...

  5. sysv-rc-conf管理Ubuntu server开机启动服务

    在RedHat中,都是使用chkconfig来管理服务的,但是在Ubuntu Server中,却有一个更好的工具,chkconfig也是可以使用的.今天来说一下sysv-rc-conf sysv-rc ...

  6. Java位运算总结-leetcode题目

    按位操作符只能用于整数基本数据类型中的单个bit中,操作符对应表格: Operator Description & 按位与(12345&1=1,可用于判断整数的奇偶性) | 按位或 ^ ...

  7. FreeMarker模板开发指南知识点梳理

    freemarker是什么? 有什么用? 怎么用? (问得好,这些都是我想知道的问题) freemarker是什么? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生 ...

  8. 如何用easyui+JAVA 实现动态拼凑datagrid表格(续)

    前面一段时间写了一篇文章: 如何用easyui+JAVA 实现动态拼凑datagrid表格 这篇文章的话,效果是可以实现,但是经过我反复试验,还是存在一些问题的. 今天这篇文章就是向大家介绍下如何避免 ...

  9. 小白Linux入门 二

    参考: http://edu.51cto.com/lesson/id-11222.html CPU中有计算单元 控制单元.它通过桥接芯片与存储器进行匹配 其中北桥是高速 南桥是低速 包括IDE USB ...

  10. jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——一些有用的Sizzle API

    说一下Sizzle中零碎的API.这些API有的被jQuery接管,直接使用jQuery.xxx就可以使用,有的没有被接管,如果要在jQuery中使用,使用方法是jQuery.find.xxx. 具体 ...