AndroidSupportDesign之TabLayout使用详解

在上一篇博客《高逼格UI-ASD(Android Support Design)》中,我们大体的对TabLayout进行了一些初步的了解,这篇博客,单独拿出TabLayout来继续讲解是因为:纵观Android Support Design库的几个控件,除了诸如:FABSnackBar等几个小控件常用以外,也就TabLayout还ok了,其他的例如CollapsingToolbarLayout,这样的控件封装性太强了,只能固定那几个场景去使用(纯属个人见解)。

TabLayout呢?上一篇博客我们只是简单的了解一下,今天这篇博客我们就用TabLayout配合ViewPager使用以下。

在开始之前,我们先来看看官网文档的说明,如何与ViewPager进行联动:

You should set a listener via setOnTabSelectedListener(OnTabSelectedListener) to be notified when any tab’s selection state has been changed.

If you’re using a ViewPager together with this layout, you can use setTabsFromPagerAdapter(PagerAdapter) which will populate the tabs using the given PagerAdapter’s page titles. You should also use a TabLayout.TabLayoutOnPageChangeListener to forward the scroll and selection changes to this layout

恩,看起来很容易啊,简单翻译一下就是:

通过setOnTabSelectedListener设置一个监听器来响应选项卡的选择状态

可以通过setTabsFromPagerAdapter来使用PagerAdapter的page title

使用TabLayout.TabLayoutOnPageChangeListener来联动滑动

ok,大体就是这样,在大体的翻译过程中,其实已经把步骤列出来了,接下来我们只需要按照上面的步骤来编写我们的代码就OK啦。

come on~,首先出场的是xml布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="#FF00FF00"
        app:tabSelectedTextColor="#FF00FF00"
        app:tabTextColor="#FF000000"
        app:tabMode="scrollable"
        app:tabGravity="center"/>

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

</LinearLayout>

恩,很简单,就是一个TabLayout和一个ViewPager,并且是上下排列的。

在Activity中,首先我们要find这两个控件:

    mTabLayout = (TabLayout) findViewById(R.id.tl);
    mViewPager = (ViewPager) findViewById(R.id.viewpager);

为了演示程序,还需要两个伪数据来充当ViewPager的内容和title。

private String[] mTitle = new String[20];
private String[] mData = new String[20];

{
    for(int i=0;i<20;i++) {
        mTitle[i] = "title" + i;
        mData[i] = "data" + i;
    }
}

下面,我们将要按照上面的步骤,一点点来撸代码啦:

第一步,设置TabLayout的选项卡监听:

mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                mViewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

当我们的tab选择时,让viewpager选中对应的item。

第二步,设置Tab的标题来自PagerAdapter.getPageTitle()

mTabLayout.setTabsFromPagerAdapter(mAdapter);

第三步,设置TabLayout.TabLayoutOnPageChangeListener,给谁设置呢?当然是ViewPager了,怎么设置呢?

final TabLayout.TabLayoutOnPageChangeListener listener =
                new TabLayout.TabLayoutOnPageChangeListener(mTabLayout);
mViewPager.addOnPageChangeListener(listener);

哦,原来TabLaout.TabLayoutOnPageChangeLisetener继承自OnPageChangeListener,不行来看:

public static class TabLayoutOnPageChangeListener implements OnPageChangeListener {...}

注意,这里是addOnPageChangeListener,也就是说,你还可以add N个Listener而不会被覆盖掉。

到这里,步骤我们都走完了,但是别忘了给ViewPage设置Adapter。

mViewPager.setAdapter(mAdapter);

最后是Adapter的代码:

private PagerAdapter mAdapter = new PagerAdapter() {
        @Override
        public CharSequence getPageTitle(int position) {
            return mTitle[position];
        }

        @Override
        public int getCount() {
            return mData.length;
        }

        @Override
        public Object instantiateItem(View container, int position) {
            TextView tv = new TextView(MainActivity.this);
            tv.setTextSize(30.f);
            tv.setText(mData[position]);
            ((ViewPager) container).addView(tv);
            return tv;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            ((ViewPager) container).removeView((View) object);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
    };

运行一下代码,看看效果:

是不是很简单? 几行代码就搞定了这种效果,当然,你也可以选择自己重写View的方式实现,可以参考我的另一篇博客《打造史上最容易使用的Tab指示符——Indicator》。

如果,你感觉这就简单,那你也太容易满足啦,Google还给我们提供了一个方法,将这些步骤封装到一块,让我们开发者可以一步搞定。public void setupWithViewPager (ViewPager viewPager),继续看看文档的说明:

The one-stop shop for setting up this TabLayout with a ViewPager.

This method will:

Add a ViewPager.OnPageChangeListener that will forward events to this TabLayout.

Populate the TabLayout’s tabs from the ViewPager’s PagerAdapter.

Set our TabLayout.OnTabSelectedListener which will forward selected events to the ViewPager

大体解释一下就是:

这个方法是addOnPageChangeListenersetOnTabSelectedListener的封装。

所以我们注释掉对应代码,替换成setupWithViewPager

//        mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
//            @Override
//            public void onTabSelected(TabLayout.Tab tab) {
//                mViewPager.setCurrentItem(tab.getPosition());
//            }
//
//            @Override
//            public void onTabUnselected(TabLayout.Tab tab) {
//
//            }
//
//            @Override
//            public void onTabReselected(TabLayout.Tab tab) {
//
//            }
//        });
        mTabLayout.setTabsFromPagerAdapter(mAdapter);

//        final TabLayout.TabLayoutOnPageChangeListener listener =
//                new TabLayout.TabLayoutOnPageChangeListener(mTabLayout);
//        mViewPager.addOnPageChangeListener(listener);
        mViewPager.setAdapter(mAdapter);
        mTabLayout.setupWithViewPager(mViewPager);

效果还是上面的效果,但是代码量明显少了,仅需两行代码搞定。

但是需要注意一下,setupWithViePager必须在ViewPager.setAdapter()之后调用!为什么呢?来源码找答案:

public void setupWithViewPager(ViewPager viewPager) {
    PagerAdapter adapter = viewPager.getAdapter();
    if(adapter == null) {
        throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
    } else {
        ...
    }
}

首先去获取该ViewPager上的Adapter,如果没有Adapter,则抛出一个异常!

好了,到现在TabLayoutViewPager一块使用的用法就讲解完了,相信还是非常简单的,仅仅两行代码就可以搞定。

在以后的项目中,肯定会经常用到它们两个好基友的,但是so easy,不怕不怕~~

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 08:46:35

AndroidSupportDesign之TabLayout使用详解的相关文章

Android Design Support Library使用详解

Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件.最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2.这不得不说是一个良心之作. 使用S

Spring事务管理(详解+实例)

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

转载:DenseNet算法详解

原文连接:http://blog.csdn.net/u014380165/article/details/75142664 参考连接:http://blog.csdn.net/u012938704/article/details/53468483 本文这里仅当学习笔记使用,具体细节建议前往原文细度. 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github链接:h

MariaDB(MySQL)创建、删除、选择及数据类型使用详解

一.MariaDB简介(MySQL简介略过) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品.在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB. MariaDB由MySQL的创始人Michael Widenius(英语:Michael Widenius)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL A

HttpServletResponse和HttpServletRequest详解

HttpServletResponse,HttpServletRequest详解 1.相关的接口 HttpServletRequest HttpServletRequest接口最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据.同时,HttpServletRequest接口可以获取由客户端传送的名称,也可以获取产生请求并且接收请求的服务器端主机名及IP地址,还可以获取客户端正在使用的通信协议等信息.下表是接口HttpServletRequest的常用方法. 说明:HttpServ

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

.NET深入解析LINQ框架(五:IQueryable、IQueryProvider接口详解)

阅读目录: 1.环路执行对象模型.碎片化执行模型(假递归式调用) 2.N层对象执行模型(纵横向对比链式扩展方法) 3.LINQ查询表达式和链式查询方法其实都是空壳子 4.详细的对象结构图(对象的执行原理) 5.IQueryable<T>与IQueryProvider一对一的关系能否改成一对多的关系 6.完整的自定义查询 1]. 环路执行对象模型.碎片化执行模型(假递归式调用) 这个主题扯的可能有点远,但是它关系着整个LINQ框架的设计结构,至少在我还没有搞懂LINQ的本意之前,在我脑海里一直频

netstat状态详解

一.生产服务器netstat tcp连接状态................................................................................ 2 1.1生产服务器某个业务LVS负载均衡上连接状态数量............................................... 2 1.2生产服务器某个业务web上连接状态数量...............................................

详解go语言的array和slice 【二】

上一篇  详解go语言的array和slice [一]已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多.上一篇的最后讲解到创建新的slice时使用第三个索引来限制slice的容量,在操作新slice时,如果新slice的容量大于长度时,添加新元素依然后使源的相应元素改变.这一篇里我会讲解到如何避免这些问题,以及迭代.和做为方法参数方面的知识点. slice的长度和容量设置为同一个值 如果在创建新的slice时我们把