ANDROID APP的页面布局(Part II)Tab Layout

在前一篇文章(ANDROID APP的页面布局(Part I))中讲到的页面布局有Linear Layout, Relative Layout ,Table Layout,这篇文章讲讲Tab Layout的使用,在早期的Andorid版本,有TabHost来实现,但是在后期的api当中这个类已经建议不在使用,建议使用fragments来使用,fragments的使用非常广泛,用来做tab是非常方便的,同时也可以用在很多种页面切换的场景或者用来切换页面里某一个部分切换的场景,比如在界面中的一个区域用来滑动显示几个图片之类的,界面非常人性化。

下面我们来使用fragments和viewpager结合完成一个Tab的效果

ViewPager 和 Fragments

ViewPager和Fragments是两个不同的组件,可以到官网查阅一下这连个组件到底是个什么东西:

http://developer.android.com/guide/components/fragments.html

http://developer.android.com/reference/android/support/v4/view/ViewPager.html

Tab Layout的原型效果

网络上找了一个标签页效果如下,其中Tab部分是Action Bar的一部分,ViewPager作为页面的主体,滑动的时候切换的页面是一个Fragments.那么整个过程包括一个主体的Activity和三个Fragments以及一个Adapter用来控制ViewPager.

image

创建项目

根据上面的原型图,我们需要创建的文件包括:

1.一个主体的Activity,在新建项目的时候就会创建了MainActivty.java,使用这个就可以了;稍微做点调整就可以了,把父类改一下继承自FragmentActivity ,并且实现接口ActionBar.TabListener如下

public class MainActivity extends FragmentActivity implements
        ActionBar.TabListener {

2.布局文件activity_main.xml也修改一下,使用ViewPager作为整个布局如下

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

3.然后创建一个Adapter用来控制VewPager的行为,也就每个Tab到底显示那个页面是有这个Adapter来控制的,继承自类FragmentPagerAdapter,我们命名为TabsPagerAdapter,这个类名可根据自己的爱好去命名

import info.androidhive.tabsswipe.GamesFragment;
import info.androidhive.tabsswipe.MoviesFragment;
import info.androidhive.tabsswipe.TopRatedFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
 
public class TabsPagerAdapter extends FragmentPagerAdapter {
 
    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
    }
 
    @Override
    public Fragment getItem(int index) {
 
        switch (index) {
        case 0:
            // Top Rated fragment activity
            return new TopRatedFragment();
        case 1:
            // Games fragment activity
            return new GamesFragment();
        case 2:
            // Movies fragment activity
            return new MoviesFragment();
        }
 
        return null;
    }
 
    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 3;
    }
 
}

添加Action Bar的标签

4.在MainActivity的方法里面给Action Bar添加标签,这里我们添加三个标签

public class MainActivity extends FragmentActivity implements
        ActionBar.TabListener {
 
    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;
    // Tab titles
    private String[] tabs = { "Top Rated", "Games", "Movies" };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // Initilization
        viewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
 
        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        
 
        // Adding Tabs
        for (String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name)
                    .setTabListener(this));
        }
效果如下
image

给标签页添加视图

5.第一个标签页的视图fragment_top_rated.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#fa6a6a" >
     
    <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Design Top Rated Screen"
        android:textSize="20dp"
        android:layout_centerInParent="true"/>
     
 
</RelativeLayout>

创建一个Fragment和这个视图对应TopRatedFragment.java

import info.androidhive.tabsswipe.R;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
public class TopRatedFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
 
        View rootView = inflater.inflate(R.layout.fragment_top_rated, container, false);
         
        return rootView;
    }
}

 

6.第二个标签页的视图fragment_games.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ff8400" >
     
    <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Design Games Screen"
        android:textSize="20dp"
        android:layout_centerInParent="true"/>
     
 
</RelativeLayout>

创建一个Fragment和这个视图对应GamesFragment.java

import info.androidhive.tabsswipe.R;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
public class GamesFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
 
        View rootView = inflater.inflate(R.layout.fragment_games, container, false);
         
        return rootView;
    }
}

 

7.第三个标签页的视图fragment_movies.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#17df0d">
     
    <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Design Movies Screen"
        android:textSize="20dp"
        android:layout_centerInParent="true"/>
     
 
</RelativeLayout>

创建一个Fragment和这个视图对应MoviesFragment.java

import info.androidhive.tabsswipe.R;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
public class MoviesFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
 
        View rootView = inflater.inflate(R.layout.fragment_movies, container, false);
         
        return rootView;
    }
 
}

 

这个标签页的三个标签之前切换的页面效果如下

image

在大屏幕下显示的效果

image

 

Tab的点击事件

因为这不是成品的Tab组件,当然网络上有一些非官方实现的一些Tab组件可以使用,这些事件和效果都实现好了,只需要添加页面就可以了,那么这里是我们自己实现的点击事件,点击某个标签,然后页面切换到对应的视图上,其实也很简单,在MainActivity.java里代码如下

@Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
 
    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // on tab selected
        // show respected fragment view
        viewPager.setCurrentItem(tab.getPosition());
    }
 
    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }

 

ViewPager的滑动事件

当在界面上左右滑动时,页面就会切换,但是Tab标签并没有跟着切换选中的状态,我们需要监听切换事件然后把对应的标签设置为选中状态,在MainActivity.java里代码如下

/**
 * on swiping the viewpager make respective tab selected
 * */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
 
    @Override
    public void onPageSelected(int position) {
        // on changing the page
        // make respected tab selected
        actionBar.setSelectedNavigationItem(position);
    }
 
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
    }
 
    @Override
    public void onPageScrollStateChanged(int arg0) {
    }
});

 

完整的代码

MainActivity.java中实现所有事件的完整代码如下

import info.androidhive.tabsswipe.adapter.TabsPagerAdapter;
import info.androidhive.tabsswipe.R;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
 
public class MainActivity extends FragmentActivity implements
        ActionBar.TabListener {
 
    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;
    // Tab titles
    private String[] tabs = { "Top Rated", "Games", "Movies" };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // Initilization
        viewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
 
        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        
 
        // Adding Tabs
        for (String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name)
                    .setTabListener(this));
        }
 
        /**
         * on swiping the viewpager make respective tab selected
         * */
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
 
            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }
 
            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }
 
            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });
    }
 
    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
 
    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // on tab selected
        // show respected fragment view
        viewPager.setCurrentItem(tab.getPosition());
    }
 
    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }
 
}

 

这就是一个完整的Tab的示例,是不是觉得很简单而且似曾相识,切实很多App的页面效果都是这么实现的,只不过呢颜色搭配不一样跟人的感脚不一样而已,同样的功能不一样的颜色搭配是有种天上地下云泥之别,所以一个懂点艺术的美工那是多么重要。

附上别人家写好的完整实例TabsWithSwipeGesture.zip