http://blog.csdn.net/harvic880925/article/details/38487149html
前言:上篇中咱们讲解了如何快速实现了一个滑动页面,但问题在于,PageAdapter必需要重写的四个函数,它们都各有什么意义,在上节的函数内部为何要这么实现,下面咱们就结合android的API说明,详细讲解一下。java
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
.android
When you implement a PagerAdapter, you must override the following methods at minimum:api
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.app
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;
.ide
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布局
提供一个适配器用于填充ViewPager页面. 你极可能想要使用一个更加具体的实现, 例如: FragmentPagerAdapter
or FragmentStatePagerAdapter
.post
当你实现一个PagerAdapter时,至少须要覆盖如下几个方法:
instantiateItem(ViewGroup, int)
destroyItem(ViewGroup, int, Object)
getCount()
isViewFromObject(View, Object)
PagerAdapter比AdapterView的使用更加普通.ViewPager使用回调函数来表示一个更新的步骤,而不是使用一个视图回收机制。在须要的时候pageradapter也能够实现视图的回收或者使用一种更为巧妙的方法来管理视图,好比采用能够管理自身视图的fragment。
网址:http://www.cnblogs.com/tony-yang-flutter/p/3591825.html
看上面的翻译,与咱们相关只有这两段话:
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。
对于上面两段话,我这里有两点要着重讲一下:
一、第一段说明了,键(Key)的概念,首先这里要清楚的一点是,每一个滑动页面都对应一个Key,并且这个Key值是用来惟一追踪这个页面的,也就是说每一个滑动页面都与一个惟一的Key一一对应。你们先有这个概念就好,关于这个Key是怎么来的,下面再讲。
二、第二段简单讲了一个应用,即将当前页面自己的View做为Key。其实这个应用就是咱们前一章讲的例子应用。不太理解?不要紧,下面细讲。下面咱们讲讲Key的问题
如今我带着你们看看几个方法的官方文档:(这里结合《ViewPager 详解(一)---基本入门》最底部的例子来看)
首先:destroyItem()
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)
.
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)返回时视图可以被移除。
下面看看《ViewPager 详解(一)---基本入门》中是如何作的:
@Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub container.removeView(viewList.get(position)); }
果不其然,咱们将给定位置的视图从container中移除了……
而后看getCount ()
Return the number of views available.
返回当前有效视图的个数。
在上一章例子中,咱们是这么作的:
@Override public int getCount() { // TODO Auto-generated method stub return viewList.size(); }
返回了当前要滑动视图的个数,与SDK说明一致。
最难的两个来了
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)
.
container | The containing View in which the page will be shown. |
---|---|
position | The page position to be instantiated. |
这个函数的实现的功能是建立指定位置的页面视图。适配器有责任增长即将建立的View视图到这里给定的container中,这是为了确保在finishUpdate(viewGroup)返回时this is be done!
返回值:返回一个表明新增视图页面的Object(Key),这里不必非要返回视图自己,也能够这个页面的其它容器。其实个人理解是能够表明当前页面的任意值,只要你能够与你增长的View一一对应便可,好比position变量也能够作为Key(最后咱们举个例子试试可不可行)
心得 :
一、从说明中能够看到,在代码中,咱们的责任是将指定position的视图添加到conatiner中
二、Key的问题:从这个函数就能够看出,该函数返回值就是咱们根据参数position增长到conatiner里的View的所对应的Key!!!!!!!
三、“it only must ensure this is done by the time it returns fromfinishUpdate(ViewGroup).”这句话在destroyItem()的函数说明中一样出现过,这说明在 finishUpdate(viewGroup)执行完后,有两个操做,一个是原视图的移除(再也不显示的视图),另外一个是新增显示视图(即将显示的视图)
在上一章的代码中,咱们是这样作的:
@Override public Object instantiateItem(ViewGroup container, int position) { // TODO Auto-generated method stub container.addView(viewList.get(position)); return viewList.get(position); } };
在这里,咱们作了两件事
第一:将参数里给定的position的视图,增长到conatiner中,供其建立并显示、。
第二:返回当前position的View作为此视图的Key。还记得API官方文档中下面这段话么?
对于很是简单的pageradapter或许你能够选择用page自己做为键,在建立而且添加到viewgroup后instantiateItem方法里返回该page自己便可destroyItem将会将该page从viewgroup里面移除。isViewFromObject方法里面直接能够返回view == object。
这里就把当前的View看成Key传过出去!!!!
最后一个: 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.
view | Page View to check for association with object |
---|---|
object | Object to check for association with view |
view
is associated with the key object object
功能:该函数用来判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是不是表明的同一个视图(即它俩是不是对应的,对应的表示同一个View)
返回值:若是对应的是同一个View,返回True,不然返回False。
在上章节的例子中,咱们这样作的:
@Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; }
因为在instantiateItem()中,咱们做为Key返回来的是当前的View,因此在这里判断时,咱们直接将Key与View看是否相等来判断是不是同一个View。
通过上面的讲解,想必你们给Key的概念应该有个清楚的理解,下面举个例子来讲明Key与View的关系,因为Key与View要一一对应,因此我把每一个视图所处的位置Position做为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); } }
在这里更改了两个地方:
一、先看Key的产生的位置instantiateItem()
@Override public Object instantiateItem(ViewGroup container, int position) { // TODO Auto-generated method stub container.addView(viewList.get(position)); //把当前新增视图的位置(position)做为Key传过去 return position; }
咱们在上讲也讲了在这个函数中Key是做为返回值与当前装入Container中的视图对应起来的。因此在这里咱们返回postion与container.addView(viewList.get(position));里的viewList.get(position)这个视图对应起来。
二、isViewFromObject ()
@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())); }
判断从instantiateItem()返回来的Key与当前的View是否能对应起来,咱们知道从instantiateItem传过来的实际上是position,因此咱们要根据position找到View,而后跟参数中的View arg0判断。
但在真正操做时出现了问题,咱们要先将obect对应转换为int类型:(int)Integer.parseInt(arg1.toString());而后再根据position找到对应的View;
效果图:三个View之间的滑动切换
这里只因此与上章不同,仅仅只有上部分一部分的地方才有滑动切换,是由于我更改了布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.testviewpage_2.MainActivity" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="wrap_content" android:layout_height="200dip" android:layout_gravity="center" /> </RelativeLayout>
这里将layout_height更改成200dip,只因此这么作,是为了告诉你们,只要在想要实现滑动切换的地方添加上<android.support.v4.view.ViewPager />就能够实现切换,无所谓位置和大小,跟普通控件同样!!!!!!