使用Material Design的控件TabLayout配合ViewPager及Fragment制作可滚动的Tab选项卡功能

时间:2023-02-13 06:26:08

前言

今天是二月的最后一天,在snatch实习已经快两个月了,从第一个月的training开始到第二个月的学习AI制作UI,学习了不少内容,算是比较充实,从三月开始就要正式进入developing阶段了,会学习到更多的知识,操练之前只是理论学习过的back-end和IOS 的xcode,安卓的develop,希望自己可以保持这个习惯,每隔一段时间记录下遇到的疑难知识点,花了很多精力解决的bug和学懂的知识。今天就从安卓的UI demo开始,遇到了之前没有做过的Tabs选项卡控件,在百度搜索了一些信息之后发现google material design将这个控件加入了库中,因此只要学习它的用法即可,不用像之前那样引入第三方库了。
在这里写的大部分内容都是翻译自google官方库的英文说明,更多可以参考以下网址:
https://developer.android.com/reference/android/support/design/widget/TabLayout.html

目录

  • 简单用法
  • 与ViewPager相结合
  • TabLayout的一些其他常用方法
  • 源代码

正文

1. 简单用法

TabLayout提供了一个水平的layout来显示tabs。
为它添加需要的tabs是通过创建TabLayout.Tab实例来实现的,对Tab对象,你可以使用setText(String)和setIcon(int)方法来设置它的标签和图标。新建对象完毕后,需要使用addTab(Tab)方法将其加入TabLayout中。

TabLayout tabLayout = ...;
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));

另一种方法是直接在layout的xml文件中为TabLayout加入子控件TabItem,并给它们设置相应的属性,原理很简单,例子可以参见下面代码。

<android.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">

<android.support.design.widget.TabItem
android:text="@string/tab_text"/>

<android.support.design.widget.TabItem
android:icon="@drawable/ic_android"/>

</android.support.design.widget.TabLayout>

当然,你也可以为其中的tab设置监听器,在tab的选择状态发生改变时执行一些命令。设置监听器时只需要调用方法setOnTabSelectedListener(OnTabSelectedListener)即可。

2. 与ViewPager相结合

若你想把ViewPager和TabLayout结合在一起,你可以调用方法setupWithViewPager(ViewPager)来将它们连接起来。这个方法帮你完成了两者中其中一个改变状态(包括滚动状态和点击事件)时另一个的视图更新。在需要使用的Activity类中写入如下代码即可:

ViewPagerAdapter adapter=new ViewPagerAdapter(getSupportFragmentManager(),fragments);
ViewPager viewPager=(ViewPager)findViewById(R.id.viewpager);
viewPager.setAdapter(adapter);
tabs.setupWithViewPager(viewPager);

当然,你需要写一个ViewPager的Adapter,当Tabs需要更新时,它会从Adapter类中获取选中的Tab标题。当然注意这里的ViewPagerAdapter需要继承自FragmentStatePagerAdapter,在重写它的方法时不要忘记public CharSequence getPageTitle(int position),就是这个方法返还了Tab的标题。ViewPagerAdapter的写法如下:

public class ViewPagerAdapter extends FragmentStatePagerAdapter {

private List<Fragment> fragments;

public ViewPagerAdapter(FragmentManager fm,List<Fragment> list) {
super(fm);
fragments=list;
}

@Override
public Fragment getItem(int position) {
return fragments.get(position);
}

@Override
public int getCount() {
return fragments.size();
}

@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
}

在这里也有另一种方法,就是直接将TabLayout在layout的xml文件中作为ViewPager的子控件写入。可以参考下例。

 <android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top" />

</android.support.v4.view.ViewPager>

3. TabLayout的一些其他常用方法

  1. setSelectedTabIndicatorColor(int color):设置Tab被选中时底部指示的小条子的颜色
  2. setSelectedTabIndicatorHeight(int height):设置Tab被选中时底部指示的小条子的高度,单位为pixel
  3. setTabGravity(int gravity):设置Tab的布局位置,它的参数有两个可选值GRAVITY_CENTER和GRAVITY_FILL。其中GRAVITY_CENTER表示将Tabs布局在TabLayout的中间位置,而GRAVITY_FILL只有在MODE_FIXED时有效,表示使得Tab尽可能地去填满TabLayout。
  4. setTabMode(int mode):设置Tab在TabLayout中的表现模式,他也有两个可选值MODE_FIXED和MODE_SCROLLABLE。其中MODE_FIXED会同时显示所有的Tab,而MODE_SCROLLABLE会显示一部分(或全部)的Tab,取决于tab的宽度,并且未显示完全时TabLayout可以左右滚动,这更适合在Tab的标题比较长或Tab比较多的时候使用。
  5. setTabTextColors(int normalColor, int selectedColor):设置不同状态(未选中,选中)下的Tab字体颜色。

这些方法在java类中对TabLayout的整体属性进行设置,一般也可以在xml中直接对属性进行设置,可以参考下面涉这段例子:

<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabs"
app:tabGravity="center"
app:tabBackground="@color/colorPrimary"
app:tabTextColor="@color/lightgrey"
app:tabIndicatorColor="@color/tabindicator"
app:tabIndicatorHeight="4dp"
app:tabSelectedTextColor="@color/white"></android.support.design.widget.TabLayout>

4. 源代码

  1. xml文件
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabs"
app:tabGravity="center"
app:tabBackground="@color/colorPrimary"
app:tabTextColor="@color/lightgrey"
app:tabIndicatorColor="@color/tabindicator"
app:tabIndicatorHeight="4dp"
app:tabSelectedTextColor="@color/white"></android.support.design.widget.TabLayout>

<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/viewpager"
android:background="@color/lightgrey"></android.support.v4.view.ViewPager>

</LinearLayout>
  1. ViewPagerAdapter的写法
package com.example.administrator.snatchuidemo;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

import java.util.List;

/**
* Created by Administrator on 2017/2/28.
*/


public class ViewPagerAdapter extends FragmentStatePagerAdapter {

private List<Fragment> fragments;
private String [] titles;

public ViewPagerAdapter(FragmentManager fm,List<Fragment> list,String[] titles) {
super(fm);
fragments=list;
this.titles=titles;
}

@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}

@Override
public Fragment getItem(int position) {
return fragments.get(position);
}

@Override
public int getCount() {
return fragments.size();
}
}
  1. Fragment的写法
    这里只列出一个Fragment的类的代码,其他的都类同,而且真正使用时需要写好fragment对应的布局xml文件,这里不列出来。
package com.example.administrator.snatchuidemo.Fragments;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.administrator.snatchuidemo.R;

/**
* Created by Administrator on 2017/2/28.
*/


public class FragmentDescription extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.description,container,false);
return view;
}
}
  1. Activity的写法
package com.example.administrator.snatchuidemo;

import android.app.Activity;
import android.app.ListFragment;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.TableLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;

import com.example.administrator.snatchuidemo.Fragments.FragmentAbout;
import com.example.administrator.snatchuidemo.Fragments.FragmentDescription;
import com.example.administrator.snatchuidemo.Fragments.FragmentMenu;
import com.example.administrator.snatchuidemo.Fragments.FragmentReviews;

import java.util.ArrayList;
import java.util.List;

/**
* Created by Administrator on 2017/2/27.
*/


public class CouponDetail extends AppCompatActivity {

private final String[] tabTitles={"Description","About","Reviews","Menu"};
private List<Fragment> fragments;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.coupon_detail);
initFragments();
initTabs();
}

private void initFragments(){
Fragment description=new FragmentDescription();
Fragment about=new FragmentAbout();
Fragment reviews=new FragmentReviews();
Fragment menu=new FragmentMenu();
fragments=new ArrayList<Fragment>();
fragments.add(description);
fragments.add(about);
fragments.add(reviews);
fragments.add(menu);
}

private void initTabs(){
TabLayout tabs=(TabLayout)findViewById(R.id.tabs);
tabs.setTabMode(TabLayout.MODE_FIXED);
for(int i=0;i<tabTitles.length;i++)
tabs.addTab(tabs.newTab().setText(tabTitles[i]));
ViewPagerAdapter adapter=new ViewPagerAdapter(getSupportFragmentManager(),fragments,tabTitles);
ViewPager viewPager=(ViewPager)findViewById(R.id.viewpager);
viewPager.setAdapter(adapter);
tabs.setupWithViewPager(viewPager);
}
}

参考资料

这里参考了CSDN上的一篇文章:
http://blog.csdn.net/crazymo_/article/details/52022389