当前位置: 代码迷 >> 综合 >> Tab导航的实现(一)-Tablayout
  详细解决方案

Tab导航的实现(一)-Tablayout

热度:97   发布时间:2024-01-04 05:58:36.0

目前主流实现方式

a 运用Material Design提供的插件TabLayout

b 运用Material Design提供的BottomNavigationView

c FragmentTabHost

一 TabLayout

资料来源:

https://blog.csdn.net/qq_23205911/article/details/73430979

准备工作

由于Material Design属于扩展库,需要实现添加依赖

 
implementation 'com.android.support:design:27.1.1'

后面的版本号必须跟V7包的版本一致

implementation 'com.android.support:appcompat-v7:27.1.1'

1.1通过代码动态实现tablayout

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"android:orientation="vertical"><FrameLayoutandroid:id="@+id/home_container"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></FrameLayout><viewandroid:layout_width="match_parent"android:layout_height="0.5dp"android:alpha="0.6"android:background="@android:color/darker_gray"/><android.support.design.widget.TabLayoutandroid:id="@+id/host_tab_layout"android:layout_width="match_parent"android:layout_height="50dp"app:tabSelectedTextColor="@android:color/black"//标题选中的颜色app:tabTextColor="@android:color/darker_gray"//未选中的颜色app:tabIndicatorHeight="0dp"></android.support.design.widget.TabLayout>
</LinearLayout>

indicator指示器

指的就是当前标签页底部的红色的线,设置属性有color和height

UI效果通过代码实现(安装并添加里ButterKnife插件)

 protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_tablayout);initView();}/*** 用ButterKnife快速绑定View控件*/private void initView() {unbinder=ButterKnife.bind(this);hostTabLayout.addTab(hostTabLayout.newTab().setText("TDab1"));hostTabLayout.addTab(hostTabLayout.newTab().setText("TDab2"));hostTabLayout.addTab(hostTabLayout.newTab().setText("TDab3"));}

1.2在布局文件中实现

 <android.support.design.widget.TabLayoutandroid:id="@+id/host_tab_layout"android:layout_width="match_parent"android:layout_height="50dp"app:tabIndicatorHeight="0dp"app:tabSelectedTextColor="@android:color/black"app:tabTextColor="@android:color/darker_gray"><android.support.design.widget.TabItemandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Tab1"/><android.support.design.widget.TabItemandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Tab2"/><android.support.design.widget.TabItemandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Tab3"/></android.support.design.widget.TabLayout>

实现效果图

1.3添加新的功能

1.4TabLayout的监听事件

hostTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {@Overridepublic void onTabSelected(TabLayout.Tab tab) {//                选中了标签的逻辑}@Overridepublic void onTabUnselected(TabLayout.Tab tab) {//                未选中tab的逻辑}@Overridepublic void onTabReselected(TabLayout.Tab tab) {//                再次选中tab的逻辑}});

三个回调接口的执行顺序

当切换新的tab时A--B

onTabUnselected(A)

onTabReselected(B)

onTabSelected(B)

当重复选择当前tab时C---C

onTabReselected(C)

 

2ViewPaper

思路

ViewPaper实现了若干个界面的滑动切换效果,通过跟tabLayout关联,实现两者的联动效果

2.1布局文件

 <android.support.v4.view.ViewPagerandroid:id="@+id/vp_context"android:layout_width="match_parent"android:layout_height="match_parent"></android.support.v4.view.ViewPager>

2.2代码实现

ViewPaper要实现若干个界面的切换,需要进行适配器填装paperadapter,目前主流的上使用FragmentPaperAdapter

创建自己的Adapter

public class FragAdapter extends FragmentPagerAdapter{private List<Fragment> mfragments=null;public FragAdapter(FragmentManager fm,List<Fragment> fragments) {super(fm);mfragments=fragments;}@Overridepublic Fragment getItem(int position) {return mfragments.get(position);}@Overridepublic int getCount() {return mfragments.size();}
}

只需要实现getItem()和getCount()方法

然后,在活动中初始化调用

//        设置FragmentListList<Fragment> fragmentList=new ArrayList<Fragment>();fragmentList.add(BlankFragment.newInstance());fragmentList.add(BlankFragment2.newInstance());fragmentList.add(BlankFragment3.newInstance());//        设置适配器并装载adapter=new FragAdapter(getSupportFragmentManager(),fragmentList);vpContext.setAdapter(adapter);

4和ViewPager的联动

有资料建议用setupWithViewPaper()关联两者,实验后,发现tab标签变成里空白,原因上在关联代码内部封装函数中,移除里所有tab

tabLayout.setupWithViewPager(Viewpager);

所以采用在监听器中回调互相指定变化

        hostTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {@Overridepublic void onTabSelected(TabLayout.Tab tab) {vpContext.setCurrentItem(tab.getPosition());
//                选中了标签的逻辑}@Overridepublic void onTabUnselected(TabLayout.Tab tab) {
//                未选中tab的逻辑}@Overridepublic void onTabReselected(TabLayout.Tab tab) {
//                再次选中tab的逻辑}});vpContext.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {hostTabLayout.getTabAt(position).select();}@Overridepublic void onPageScrollStateChanged(int state) {}});

填坑:

1,我自己理解的上,在ViewPaper变化时,应该在onPageScrolled()方法中设置标签,结果造成通过标签无法切换界面

个人认为因为nPageScrolled()的不断调用,阻止了界面的变化.

实际上应该在onPageSelected()中设置tab的标签.

参考资料:https://www.cnblogs.com/Dionexin/p/5727297.html

ViewPaper监听器的方法执行顺序:

用手指拖动翻页时,最先执行一遍onPageScrollStateChanged(1),然后不断执行onPageScrolled,放手指的时候,直接立即执行一次onPageScrollStateChanged(2),然后立即执行一次onPageSelected,然后再不断执行onPageScrollStateChanged,最后执行一次onPageScrollStateChanged(0)。

通过setCurrentItem()设置界面的时候,直接立即执行一次onPageScrollStateChanged(2),然后立即执行一次onPageSelected,然后再不断执行onPageScrollStateChanged,最后执行一次onPageScrollStateChanged(0)。

2.限定vieewPager预加载数量

通过vp.setOffscreenPageLimit()方法,可以指定加载当前frag时,提前加载frag的数量.

默认的设置是自动预加载下一个页面,最多持有当前frag,上一个和下一个3个frag,多余的frag会被销毁

如果我们的页面固定显示4个,直接用该方法,设置viewPager加载4个页面即可.

 

 

3 实现标签选中跟未选中的变化

3.1tablayout自带的标签

首先,对图标和标签标题进行数组管理

        final int[] tabResPressed=new int[]{R.drawable.ic_left,R.drawable.ic_stop,R.drawable.ic_right};final int[] tabRes=new int[]{R.drawable.ic_insmall,R.drawable.ic_location,R.drawable.ic_inbigger};final String[] tabTitle=new String[]{"tab1","tab2","tab3"};

第二步,通过数组初始化标签图标,(文本和图标两部分)

文本 tab.setText(string)

图标 tab.setIcon(resources)

//        给TablLayout添加标签for(int i=0;i<tabTitle.length;i++){hostTabLayout.addTab(hostTabLayout.newTab().setText(tabTitle[i]).setIcon(getResources().getDrawable(tabRes[i])));}

第三步,在tablayout的监听器中,对选中图标进行设置

A---B,设置B

@Overridepublic void onTabSelected(TabLayout.Tab tab) {
//                ViewPaper联动vpContext.setCurrentItem(tab.getPosition());
//                图标变为选中状态for (int i=0;i<tabTitle.length;i++){if (tab.getText().equals(tabTitle[i])){tab.setIcon(tabResPressed[i]);}}}

第四步,对tablayout监听器中,对原来被选中的图标更新图标

A--B,设置A

           @Overridepublic void onTabUnselected(TabLayout.Tab tab) {
//                图标变回未选中状态for (int i=0;i<tabTitle.length;i++){if (tab.getText().equals(tabTitle[i])){tab.setIcon(tabRes[i]);}}
//                未选中tab的逻辑}

第五步,设置默认  

/        设置默认选中第一个tab并改变图标hostTabLayout.getTabAt(0).select();setIconViewSelected(0);

具体的实现方法

    private void setIconView(TabLayout.Tab tab,int position) {View mView=tab.getCustomView();ImageView mImageView=(ImageView) mView.findViewById(R.id.iv_icon);TextView mtextView=(TextView)mView.findViewById(R.id.tv_title);mImageView.setImageResource(tabRes[position]);mtextView.setTextColor(getResources().getColor(android.R.color.darker_gray));}private void setIconViewSelected(int position) {View mView=hostTabLayout.getTabAt(position).getCustomView();ImageView mImageView=(ImageView) mView.findViewById(R.id.iv_icon);TextView mtextView=(TextView)mView.findViewById(R.id.tv_title);mImageView.setImageResource(tabResPressed[position]);mtextView.setTextColor(getResources().getColor(android.R.color.black));}

 

 

github地址:

 

https://github.com/wwqby/MyApplication.git