ViewPager 用途比较广泛,本篇文章将会谈谈 ViewPager 和 PagerAdapter 的相关使用。
最简单的 ViewPager
下面展示一个非常简单的 ViewPager 效果的实现:
1 | public class MainActivity extends AppCompatActivity { |
其中,layout1.xml 的文件布局如下:
1 | <?xml version="1.0" encoding="utf-8"?> |
layout2.xml 的文件布局如下:
1 | <?xml version="1.0" encoding="utf-8"?> |
layout3.xml 的布局文件如下:
1 | <?xml version="1.0" encoding="utf-8"?> |
OK,一个最简单的 ViewPager 效果就完成了。
LayoutInflater技术广泛应用于需要动态添加View的时候,比如在ScrollView和ListView中,经常都可以看到LayoutInflater的身影。
LayoutInflater 不是今天的重点,今天讨论的重点是 PagerAdapter。
PagerAdapter 解析
PagerAdapter 和 ListView、GridView 里面使用到的 Adapter 不同。PagerAdapter 并没有使用回收机制,而是通过回调的方式来表明每次更新界面的操作流程。当然,如果你需要操作复杂的界面, PagerAdapter 也能实现视图回收。
ViewPager 完整的界面更新流程如下:当 PagerAdapter调用了 startUpdate(ViewGourp)
方法时,表明 ViewPager 中的内容将要发生改变。接着就会调用 instantiateItem(ViewGroup, int)
以及/或者 destroyItem(ViewGourp, int, Object)
方法,最后会以调用 finishUpdate(ViewGroup)
作为结束。
上面说到的几个方法里面,总共有三个参数对象,这几个方法里面的参数含义是一样的。ViewGroup
的对象 container
表示 ViewPager 的视图容器。int
类型的参数 position
表示页面视图的顺序位置。而 Object
对象是一个键,用来表示视图对象的引用。
那么什么是键呢?键用来干嘛?
首先,ViewPager 并不会直接操作视图,而是将每一个页面视图与一个键(key Object)关联起来,通过操作键来获取到引用视图进行操作。这个键是用来跟踪以及唯一标识一个独立的页面视图。当调用了 instantiateItem(ViewGroup, int)
方法创建一个页面视图并将其添加进视图容器 container
之后,需要返回一个对象(Object)作为键,作为该页面视图的引用,一个非常简单的 PagerAdapter 可以选择使用页面视图本身(一个 View)作为一个键,就像开头的那个例子一样,当然你也可以自定义一个键。同时,isViewFromObject(View, Object)
这个方法用于判断当前页面视图 View 是否是与该键(Object)关联的 View,因此该方法的实现方式一般都固定是 return view == object;
。
以上就是 PagerAdapter 相关的核心内容,结合最开始的例子,希望大家都能够看明白。下面将 PagerAdapter 需要重写的4个方法进行简单说明:
- destroyItem(ViewGroup container, int position, Object object)
移除指定位置的页面。该 Adapter 负责在 finishUpdate()
方法返回时从容器删除视图。
这个很简单,直接像下面的方法实现一样就行:
1 |
|
- getCount ()
返回可用视图的数量。
同样很简单,实现方法如下:
1 |
|
- instantiateItem (ViewGroup container, int position)
创建指定位置的页面,该 Adapter 负责将视图添加进当前的容器(container),并返回一个键(key),用来关联当前的页面视图 View。
实现的方法一般是:
1 |
|
- isViewFromObject(View view, Object object)
判断instantiateItem(ViewGroup, int) 方法所返回来的 Key 与一个页面视图是否是代表的同一个视图(即它俩是否是对应的,对应的表示同一个View)。
一般实现方法如下:
1 |
|
自定义 Key
前面说到,一个非常简单的 PagerAdapter 可以选择使用页面视图本身(一个 View)作为一个键。那么很多人会想到(包括我):为什么通常使用视图本身(View 对象)作为键,而不是视图位置(int 类型参数 position)呢?
下面我们就来实现自定义 Key:使用 int 类型的参数作为键。其他的不变,我们只看一下 PagerAdapter 的实现:
1 | mAdapter = new PagerAdapter() { |
其实,修改的也只有 isViewFromObject()
和 instantiateItem()
两个方法。在 instantiateItem()
方法中我们返回了当前视图位置 position 作为键,而在 isViewFromObject()
方法中,为了获取该键所引用的 view,需要将 object 对象进行强制转换获取 positon,然后从视图容器集合中取出 view。私以为这样做比较麻烦,还不如原来将 view 作为键来的方便。