原文出处:http://chenfuduo.me/2015/07/30/TabLayout-of-design-support-library/

在开发中,我们常常需要ViewPager结合Fragment一起使用,如下图:
1

我们可以使用三方开源的PagerSlidingTabStrip去实现,或者viewpagerindicator,我一般都偏向前者。现在我们可以使用Design support library库的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">
    <!--app:tabMode="scrollable"  这个属性我在代码中设置了-->
   <!-- tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);-->
    <android.support.design.widget.TabLayout
        android:id="@+id/sliding_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         />
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"
        android:background="@android:color/white" />
</LinearLayout>
在xml添加TabLayout,如同ViewPager,直接`android.support.design.widget.TabLayout`即可。还有其他的属性我会在代码中设置。

创建Fragment

package me.chenfuduo.myfragmentdemo.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import me.chenfuduo.myfragmentdemo.R;
/**
 * Created by Administrator on 2015/7/30.
 */
public class PageFragment extends Fragment {
    public static final String ARG_PAGE = "ARG_PAGE";
    private int mPage;
    public static PageFragment newInstance(int page) {
        Bundle args = new Bundle();
        args.putInt(ARG_PAGE, page);
        PageFragment pageFragment = new PageFragment();
        pageFragment.setArguments(args);
        return pageFragment;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPage = getArguments().getInt(ARG_PAGE);
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_page, container, false);
        TextView textView = (TextView) view;
        textView.setText("Fragment #" + mPage);
        return view;
    }
}

其中Fragment的布局为:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" />

ViewPager的适配器

package me.chenfuduo.myfragmentdemo.adapter;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import me.chenfuduo.myfragmentdemo.fragment.PageFragment;
/**
 * Created by Administrator on 2015/7/30.
 */
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
    final int PAGE_COUNT = 3;
    private String tabTitles[] = new String[]{"tab1","tab2","tab3"};
    private Context context;
    public SimpleFragmentPagerAdapter(FragmentManager fm,Context context) {
        super(fm);
        this.context = context;
    }
    @Override
    public Fragment getItem(int position) {
        return PageFragment.newInstance(position + 1);
    }
    @Override
    public int getCount() {
        return PAGE_COUNT;
    }
    @Override
    public CharSequence getPageTitle(int position) {
        return tabTitles[position];
    }
}

设置TabLayout

package me.chenfuduo.myfragmentdemo;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
import me.chenfuduo.myfragmentdemo.adapter.SimpleFragmentPagerAdapter;
public class ThirdActivity extends FragmentActivity {
    private SimpleFragmentPagerAdapter pagerAdapter;
    private ViewPager viewPager;
    private TabLayout tabLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
        pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(pagerAdapter);
        tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);
    }
}

这里提几点我遇到的问题

  • tabLayout.setTabMode(TabLayout.MODE_FIXED);

开始我设置的是:

tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

运行后,三个TabLayout标签挤到一块去了。如下:

查看api,找到结果了。这个tabmode有两个属性值:

  • MODE_FIXED:Fixed tabs display all tabs concurrently and are best used with content that benefits from quick pivots between tabs.

  • MODE_SCROLLABLE:Scrollable tabs display a subset of tabs at any given moment, and can contain longer tab labels and a larger number of tabs.

不做过多的解释,MODE_SCROLLABLE适合很多tabs的情况。

  • setupWithViewPager必须在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 {
        ...
    }
}

以上就是最基本的用法,是不是很简单。哈~

定义TabLayout的样式

默认的情况下,TabLayout的tab indicator的颜色是Material Design中的accent color(#009688),我们可以稍作修改:

<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
    <item name="tabIndicatorColor">#0000FF</item>
</style>

在布局中使用:

<android.support.design.widget.TabLayout
       android:id="@+id/sliding_tabs"
       style="@style/MyCustomTabLayout"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
        />

还有一些其他的样式可供选择:

<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
    <item name="tabMaxWidth">@dimen/tab_max_width</item>
    <item name="tabIndicatorColor">?attr/colorAccent</item>
    <item name="tabIndicatorHeight">2dp</item>
    <item name="tabPaddingStart">12dp</item>
    <item name="tabPaddingEnd">12dp</item>
    <item name="tabBackground">?attr/selectableItemBackground</item>
    <item name="tabTextAppearance">@style/MyCustomTabTextAppearance</item>
    <item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>
<style name="MyCustomTabTextAppearance" parent="TextAppearance.Design.Tab">
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">?android:textColorSecondary</item>
    <item name="textAllCaps">true</item>
</style>

添加icon到tab

当前的TabLayout没有方法让我们去添加icon,我们可以使用SpannableString结合ImageSpan来实现,在SimpleFragmentPagerAdapter中:

private int[] imageResId = {
        R.drawable.ic_one,
        R.drawable.ic_two,
        R.drawable.ic_three
};
// ...
@Override
public CharSequence getPageTitle(int position) {
    // Generate title based on item position
    // return tabTitles[position];
    Drawable image = context.getResources().getDrawable(imageResId[position]);
    image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
    SpannableString sb = new SpannableString(" ");
    ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
    sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return sb;
}

运行,发现没有显示,这是因为TabLayout创建的tab默认设置textAllCaps属性为true,这阻止了ImageSpan被渲染出来,可以通过下面的样式文件定义来改变:

<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
      <item name="tabTextAppearance">@style/MyCustomTextAppearance</item>
</style>
<style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
      <item name="textAllCaps">false</item>
</style>

现在运行,效果就出来了。

添加icon和text到tab

@Override
public CharSequence getPageTitle(int position) {
    // Generate title based on item position
    Drawable image = context.getResources().getDrawable(imageResId[position]);
    image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
    // Replace blank spaces with image icon
    SpannableString sb = new SpannableString("   " + tabTitles[position]);
    ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
    sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return sb;
}

我们看到在实例化SpannableString的时候,我在tabTitles[position]前面加了几个空格,这些空格的位置是用来放置icon的。

添加自定义的view到tab

适配器中增加getTabView(...)方法:

package me.chenfuduo.myfragmentdemo.adapter;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import me.chenfuduo.myfragmentdemo.R;
import me.chenfuduo.myfragmentdemo.fragment.PageFragment;
/**
 * Created by Administrator on 2015/7/30.
 */
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
    final int PAGE_COUNT = 3;
    private String tabTitles[] = new String[]{"tab1", "tab2", "tab3"};
    private int[] imageResId = {R.drawable.avatar_enterprise_vip,
            R.drawable.avatar_grassroot,
            R.drawable.avatar_vip};
    private Context context;
    public SimpleFragmentPagerAdapter(FragmentManager fm, Context context) {
        super(fm);
        this.context = context;
    }
    @Override
    public Fragment getItem(int position) {
        return PageFragment.newInstance(position + 1);
    }
    @Override
    public int getCount() {
        return PAGE_COUNT;
    }
    @Override
    public CharSequence getPageTitle(int position) {
        //第一次的代码
        //return tabTitles[position];
        //第二次的代码
       /**
         Drawable image = context.getResources().getDrawable(imageResId[position]);
        image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
        SpannableString sb = new SpannableString(" " + tabTitles[position]);
        ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
        sb.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return sb;*/
        return null;
    }
    public View getTabView(int position){
        View view = LayoutInflater.from(context).inflate(R.layout.tab_item, null);
        TextView tv= (TextView) view.findViewById(R.id.textView);
        tv.setText(tabTitles[position]);
        ImageView img = (ImageView) view.findViewById(R.id.imageView);
        img.setImageResource(imageResId[position]);
        return view;
    }
}

简单的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:layout_centerVertical="true"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/imageView"
        android:layout_centerVertical="true"
        android:id="@+id/textView"
        android:layout_marginLeft="3dp"
        />
</RelativeLayout>

使用:

@Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_third);
       pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
       viewPager = (ViewPager) findViewById(R.id.viewpager);
       viewPager.setAdapter(pagerAdapter);
       tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
       tabLayout.setupWithViewPager(viewPager);
       tabLayout.setTabMode(TabLayout.MODE_FIXED);
       for (int i = 0; i < tabLayout.getTabCount(); i++) {
           TabLayout.Tab tab = tabLayout.getTabAt(i);
           tab.setCustomView(pagerAdapter.getTabView(i));
       }
   }

处理配置改变

当屏幕旋转或者配置改变的时候,我们需要保存当前的状态。

@Override
   public void onSaveInstanceState(Bundle outState) {
       super.onSaveInstanceState(outState);
       outState.putInt(POSITION,tabLayout.getSelectedTabPosition());
   }
   @Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {
       super.onRestoreInstanceState(savedInstanceState);
       viewPager.setCurrentItem(savedInstanceState.getInt(POSITION));
   }

需要注意的是getSelectedTabPosition()方法是最新的design support library才有的。
最后的效果如下:

转 android design library提供的TabLayout的用法的更多相关文章

  1. android design library提供的TabLayout的用法

    在开发中,我们常常需要ViewPager结合Fragment一起使用,如下图: 我们可以使用三方开源的PagerSlidingTabStrip去实现,或者viewpagerindicator,我一般都 ...

  2. Android - 用Fragments实现动态UI - 使用Android Support Library

    Android Support Library提供了一个带有API库的JAR文件来让你可以在使用最新的Android API的同时也也已在早期版本的Android上运行.例如,Support Libr ...

  3. 【Android】10.2 使用Android Support Library增强组件功能

    分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 Android Support Library提供了一些非常漂亮的附加功能,由于这些库的引用办法都差不多,所以这一 ...

  4. Android Design Support Library(一)用TabLayout实现类似网易选项卡动态滑动效果

    这里我们用TabLayout来实现这一效果.TabLayout是Android Design Support Library库中的控件.Google在2015的IO大会上,给我们带来了更加详细的Mat ...

  5. Android Design Support Library使用详解

    Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ...

  6. 【转】【翻】Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

    转自:http://mrfufufu.github.io/android/2015/07/01/Codelab_Android_Design_Support_Library.html [翻]Andro ...

  7. Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

    原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session--Make your app fanc ...

  8. Material Design 开发利器:Android Design Support Library 介绍

    转自:https://blog.leancloud.cn/3306/ Android 5.0 Lollipop 是迄今为止最重大的一次发布,很大程度上是因为 material design —— 这是 ...

  9. Android Design Support Library(三)用CoordinatorLayout实现Toolbar隐藏和折叠

    此文的代码在Android Design Support Library(一)用TabLayout实现类似网易选项卡动态滑动效果代码的基础上进行修改,如果你没有看过本系列的第一篇文章最好先看一看.Co ...

随机推荐

  1. ☕【Java技术指南】「序列化系列」深入挖掘FST快速序列化压缩内存的利器的特性和原理

    FST的概念和定义 FST序列化全称是Fast Serialization Tool,它是对Java序列化的替换实现.既然前文中提到Java序列化的两点严重不足,在FST中得到了较大的改善,FST的特 ...

  2. C语言的“隐式函数声明”违背了 “前置声明” 原则

    这个问题来源于小组交流群里的一个问题: 最终问题落脚在 : 一个函数在main中调用了,必须在main之前定义或者声明吗? 我在自己的Centos上做了实验,结果是函数不需要,但是结构体(变量也要)需 ...

  3. robot framework 导入资源

    创建资源后添加关键字 创建资源文件用于存放关键字,项目下的所有套件都可以引用. 1.创建资源 测试项目->new resource->输入资源名称->点击"确认" ...

  4. (数据科学学习手札130)利用geopandas快捷绘制在线地图

    本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在上一篇文章中,我为大家介绍了不久前发布的 ...

  5. 我罗斯方块最终篇(Block类)

    负责的任务 完善Block类的相关函数及变量: 对Block类中函数进行调整改进,并于其他人负责的类相互配合: 对Block类的函数功能进行调试: github项目地址. 效果图 具体可见总篇,一下仅 ...

  6. React-Router学习(基础路由与嵌套路由)

    示例:基本路由 在这个例子中,我们有3个'Page'组件处理<Router>. 注意:而不是<a href="/">我们使用<Link to=&quo ...

  7. Python | Python语法基础

    目录 前言 1. 变量与简单数据结构 2. 列表相关 3. 集合 4. If语句 5. 字典 6. 用户输入和while循环 7. 函数 8. 类与对象 9. 文件 10. 异常 11. 测试 最后 ...

  8. 算法学习->整数拆分问题

    动态规划典型题目/ 00 题目 将正整数n无需拆分为最大数为k的拆分方案有多少种?​要求所有的拆分方案不重复. 示例: 输入:n=5,k=5 输出:(5,5)=7 示例分析: 5=5 5=4+1 5= ...

  9. Linux 软连接与硬连接 区别

    先说结论 软连接相当于快捷方式,访问软连接会被替换为其指向的绝对路径,如果其指向的文件被删除,则无法访问. 硬连接相当于指针,与它指向的文件都指向相同的inode,当其指向的文件被删除,inode由于 ...

  10. 【IDEA】IntelliJ IDEA 2020.1破解版

    IntelliJ IDEA 2020.1破解版 2020-09-09  14:58:56  by冲冲 安装链接: 1. 百度网盘下载地址链接:https://pan.baidu.com/s/1cxjz ...