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 />就能夠實現切換,無所謂位置和大小,跟普通控件同樣!!!!!!