前言:这里只是对 ViewPager的一个简单的使用介绍,参考自博客http://blog.csdn.net/harvic880925/article/details/38453725 。
一个小例子
1.向注布局中添加
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context="com.example.testviewpage_1.MainActivity" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</RelativeLayout>
2.新建三个layout,用于滑动切换的视图(不一一列举)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical" >
<!--内部可以添加自己的控件-->
</LinearLayout>
这里写代码片
3.MainActivity
import java.util.ArrayList;
import java.util.List;
import java.util.zip.Inflater;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends Activity {
private View view1, view2, view3;//相对应的三个View
private ViewPager viewPager; //对应的viewPager
private List<View> viewList;//view数组
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewpager);
LayoutInflater inflater=getLayoutInflater();
view1 = inflater.inflate(R.layout.layout1, null);//初始化View
view2 = inflater.inflate(R.layout.layout2,null);
view3 = inflater.inflate(R.layout.layout3, null);
viewList = new ArrayList<View>();// 将要分页显示的View装入数组中
viewList.add(view1);
viewList.add(view2);
viewList.add(view3);
PagerAdapter pagerAdapter = new PagerAdapter() {
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == arg1;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return viewList.size();
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
// TODO Auto-generated method stub
container.removeView(viewList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(viewList.get(position));
return viewList.get(position);
}
};
viewPager.setAdapter(pagerAdapter);
}
}
具体实例是为了便于后边的说明,仅供参考。
ViewPager的官方SDK
1.官方文档
Base class providing the adapter to populate pages inside of a ViewPager. You will most likely want to use a more specific implementation of this, such as FragmentPagerAdapter orFragmentStatePagerAdapter.
When you implement a PagerAdapter, you must override the following methods at minimum:
- instantiateItem(ViewGroup, int)
- destroyItem(ViewGroup, int, Object)
- getCount()
- isViewFromObject(View, Object)
PagerAdapter is more general than the adapters used for AdapterViews. Instead of providing a View recycling mechanism directly ViewPager uses callbacks to indicate the steps taken during an update. A PagerAdapter may implement a form of View recycling if desired or use a more sophisticated method of managing page Views such as Fragment transactions where each page is represented by its own Fragment.
ViewPager associates each page with a key Object instead of working with Views directly. This key is used to track and uniquely identify a given page independent of its position in the adapter. A call to the PagerAdapter method startUpdate(ViewGroup) indicates that the contents of the ViewPager are about to change. One or more calls to instantiateItem(ViewGroup, int) and/ordestroyItem(ViewGroup, int, Object) will follow, and the end of an update will be signaled by a call to finishUpdate(ViewGroup). By the time finishUpdate returns the views associated with the key objects returned by instantiateItem should be added to the parent ViewGroup passed to these methods and the views associated with the keys passed to destroyItem should be removed. The method isViewFromObject(View, Object) identifies whether a page View is associated with a given key object.
A very simple PagerAdapter may choose to use the page Views themselves as key objects, returning them from instantiateItem(ViewGroup, int) after creation and adding them to the parent ViewGroup. A matching destroyItem(ViewGroup, int, Object) implementation would remove the View from the parent ViewGroup and isViewFromObject(View, Object) could be implemented as return view == object;.
PagerAdapter supports data set changes. Data set changes must occur on the main thread and must end with a call to notifyDataSetChanged() similar to AdapterView adapters derived fromBaseAdapter. A data set change may involve pages being added, removed, or changing position. The ViewPager will keep the current page active provided the adapter implements the methodgetItemPosition(Object).
网址:http://developer.android.com/reference/android/support/v4/view/PagerAdapter.html
2.翻译
提供一个适配器用于填充ViewPager页面. 你很可能想要使用一个更加具体的实现, 例如: FragmentPagerAdapter or FragmentStatePagerAdapter.
当你实现一个PagerAdapter时,至少需要覆盖以下几个方法:
instantiateItem(ViewGroup, int)
destroyItem(ViewGroup, int, Object)
getCount()
isViewFromObject(View, Object)
PagerAdapter比AdapterView的使用更加普通.ViewPager使用回调函数来表示一个更新的步骤,而不是使用一个视图回收机制。在需要的时候pageradapter也可以实现视图的回收或者使用一种更为巧妙的方法来管理视图,比如采用可以管理自身视图的fragment。
viewpager不直接处理每一个视图而是将各个视图与一个键联系起来。这个键用来跟踪且唯一代表一个页面,不仅如此,该键还独立于这个页面所在adapter的位置。当pageradapter将要改变的时候他会调用startUpdate函数,接下来会调用一次或多次的instantiateItem或者destroyItem。最后在更新的后期会调用finishUpdate。当finishUpdate返回时 instantiateItem返回的对象应该添加到父ViewGroup destroyItem返回的对象应该被ViewGroup删除。methodisViewFromObject(View, Object)代表了当前的页面是否与给定的键相关联。
对于非常简单的pageradapter或许你可以选择用page本身作为键,在创建并且添加到viewgroup后instantiateItem方法里返回该page本身即可
destroyItem将会将该page从viewgroup里面移除。isViewFromObject方法里面直接可以返回view == object。
pageradapter支持数据集合的改变,数据集合的改变必须要在主线程里面执行,然后还要调用notifyDataSetChanged方法。和baseadapter非常相似。数据集合的改变包括页面的添加删除和修改位置。viewpager要维持当前页面是活动的,所以你必须提供getItemPosition方法。
3.解读
viewpager不直接处理每一个视图而是将各个视图与一个键联系起来。这个键用来跟踪且唯一代表一个页面,不仅如此,该键还独立于这个页面所在adapter的位置。当pageradapter将要改变的时候他会调用startUpdate函数,接下来会调用一次或多次的instantiateItem或者destroyItem。最后在更新的后期会调用finishUpdate。当finishUpdate返回时 instantiateItem返回的对象应该添加到父ViewGroup destroyItem返回的对象应该被ViewGroup删除。methodisViewFromObject(View, Object)代表了当前的页面是否与给定的键相关联。
对于非常简单的pageradapter或许你可以选择用page本身作为键,在创建并且添加到viewgroup后instantiateItem方法里返回该page本身即可destroyItem将会将该page从viewgroup里面移除。isViewFromObject方法里面直接可以返回view == object。
PS: 这里的key值作为一个唯一标识View的值,每个View单一映射一个Key值,key值可以整型、可以是float、也同样可以是字符类,甚至是View本身,但是当你使用了自己的Key值时,你需要相应的将 isViewFromObject (View view, Object object)、instantiateItem (ViewGroup container, int position)进行重写。
4.关于Key值的使用
先看上述需要重写的四个函数的声明:
1.destoryItem()
public void destroyItem (ViewGroup container, int position, Object object)
Remove a page for the given position. The adapter is responsible for removing the view from its Container, although it only must ensure this is done by the time it returns fromfinishUpdate(ViewGroup).
Parameters
container The containing View from which the page will be removed.
position The page position to be removed.
object The same object that was returned by instantiateItem(View, int).
这个方法实现的功能为移除一个指定的位置的页面,适配器有责任从容器中删除这个视图,这是确保finishUpdate(viewGroup)返回时视图能够被移除。
2.getCount()
public abstract int getCount ()
Return the number of views available.
返回当前有效视图的个数。
3.instantiateItem (ViewGroup container, int position)
public Object instantiateItem (ViewGroup container, int position)
Create the page for the given position. The adapter is responsible for adding the view to the container given here, although it only must ensure this is done by the time it returns fromfinishUpdate(ViewGroup).
Parameters
container The containing View in which the page will be shown.
position The page position to be instantiated.
Returns
Returns an Object representing the new page. This does not need to be a View, but can be some other container of the page.
这个函数的实现的功能是创建指定位置的页面视图。适配器有责任增加即将创建的View视图到这里给定的container中,这是为了确保在finishUpdate(viewGroup)返回时this is be done!
返回值:返回一个代表新增视图页面的Object(Key),这里没必要非要返回视图本身,也可以这个页面的其它容器。
4. isViewFromObject (View view, Object object)
public abstract boolean isViewFromObject (View view, Object object)
Determines whether a page View is associated with a specific key object as returned by instantiateItem(ViewGroup, int). This method is required for a PagerAdapter to function properly.
Parameters
view Page View to check for association with object
object Object to check for association with view
Returns
true if view is associated with the key object object
功能:该函数用来判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是代表的同一个视图(即它俩是否是对应的,对应的表示同一个View)
返回值:如果对应的是同一个View,返回True,否则返回False。
我个人理解,此时的容器即为在主布局中的ViewPager的布局区,而页面发生切换的时候将上一个在容器内的视图进行销毁,将即将出现的视图创建,所以我们需要确保,想要实现的滑动的页面数,以及重写销毁视图的方法,确认视图已经被销毁,以及对于视图的创建的重写,以及判断产生的视图是否为我们需要的视图,而这里就需要我们的key值来找到应该加载的视图。这就是我们重写上述4个函数的意义。
自定义key实例
package com.example.testviewpage_2;
/**
* @author harvic
* @date 2014.8.11
*/
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends Activity {
private View view1, view2, view3;
private List<View> viewList;// view数组
private ViewPager viewPager; // 对应的viewPager
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewpager);
LayoutInflater inflater = getLayoutInflater();
view1 = inflater.inflate(R.layout.layout1, null);
view2 = inflater.inflate(R.layout.layout2, null);
view3 = inflater.inflate(R.layout.layout3, null);
viewList = new ArrayList<View>();// 将要分页显示的View装入数组中
viewList.add(view1);
viewList.add(view2);
viewList.add(view3);
PagerAdapter pagerAdapter = new PagerAdapter() {
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
//根据传来的key,找到view,判断与传来的参数View arg0是不是同一个视图
return arg0 == viewList.get((int)Integer.parseInt(arg1.toString()));
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return viewList.size();
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
// TODO Auto-generated method stub
container.removeView(viewList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(viewList.get(position));
//把当前新增视图的位置(position)作为Key传过去
return position;
}
};
viewPager.setAdapter(pagerAdapter);
}
}
最后介绍两个子控件
1.PagerTabStrip
PagerTitleStrip is a non-interactive indicator of the current, next, and previous pages of a ViewPager. It is intended to be used as a child view of a ViewPager widget in your XML layout. Add it as a child of a ViewPager in your layout file and set its android:layout_gravity to TOP or BOTTOM to pin it to the top or bottom of the ViewPager. The title from each page is supplied by the methodgetPageTitle(int) in the adapter supplied to the ViewPager.
翻译:
PagerTabStrip是ViewPager的一个关于当前页面、上一个页面和下一个页面的一个非交互的指示器。它经常作为ViewPager控件的一个子控件被被添加在XML布局文件中。在你的布局文件中,将它作为子控件添加在ViewPager中。而且要将它的 android:layout_gravity 属性设置为TOP或BOTTOM来将它显示在ViewPager的顶部或底部。每个页面的标题是通过适配器的getPageTitle(int)函数提供给ViewPager的。
For an interactive indicator, see PagerTabStrip.
这里PagerTabStrip的使用:
1、首先,文中提到:在你的布局文件中,将它作为子控件添加在ViewPager中。
实例:
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="200dip"
android:layout_gravity="center">
<android.support.v4.view.PagerTitleStrip
android:id="@+id/pagertitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
/>
</android.support.v4.view.ViewPager>
2、第二,标题的获取,是重写适配器的getPageTitle(int)函数来获取的。
部分代码:
titleList = new ArrayList<String>();// 每个页面的Title数据
titleList.add("王鹏");
titleList.add("姜语");
titleList.add("结婚");
PagerAdapter pagerAdapter = new PagerAdapter() {
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
//根据传来的key,找到view,判断与传来的参数View arg0是不是同一个视图
return arg0 == viewList.get((int)Integer.parseInt(arg1.toString()));
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return viewList.size();
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
// TODO Auto-generated method stub
container.removeView(viewList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(viewList.get(position));
//把当前新增视图的位置(position)作为Key传过去
return position;
}
@Override //进行重写
public CharSequence getPageTitle(int position) {
// TODO Auto-generated method stub
return titleList.get(position);
}
};
2.PagerTitleStrip
Class Overview
PagerTabStrip is an interactive indicator of the current, next, and previous pages of a ViewPager. It is intended to be used as a child view of a ViewPager widget in your XML layout. Add it as a child of a ViewPager in your layout file and set its android:layout_gravity to TOP or BOTTOM to pin it to the top or bottom of the ViewPager. The title from each page is supplied by the methodgetPageTitle(int) in the adapter supplied to the ViewPager.
For a non-interactive indicator, see PagerTitleStrip.
翻译:
PagerTabStrip是ViewPager的一个关于当前页面、上一个页面和下一个页面的一个可交互的指示器。它经常作为ViewPager控件的一个子控件被被添加在XML布局文件中。在你的布局文件中,将它作为子控件添加在ViewPager中。而且要将它的 android:layout_gravity 属性设置为TOP或BOTTOM来将它显示在ViewPager的顶部或底部。每个页面的标题是通过适配器的getPageTitle(int)函数提供给ViewPager的。
可以看到,除了第一句以外的其它句与PagerTitleStrip的解释完全相同。即用法也是相同的。只是PagerTabStrip是可交互的,而PagerTitleStrip是不可交互的区别。对于区别在哪些位置,即是上面的两点(是否可点击与下划线指示条)。
与上一个控件相比:
1、PagerTabStrip在当前页面下,会有一个下划线条来提示当前页面的Tab是哪个。
2、PagerTabStrip的Tab是可以点击的,当用户点击某一个Tab时,当前页面就会跳转到这个页面,而PagerTitleStrip则没这个功能。
3、PagerTitleStrip使用与PagerTabStrip基本一致。
但是由于是自带的子控件,所以在使用中的 表现并不尽如人意。所以不再介绍自定义下划线的方法,详情请查看http://blog.csdn.net/harvic880925/article/details/38557517