Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ViewPage解析(二)

ViewPage解析(二)

編輯:關於Android編程

1. SDK講解

提供一個適配器用於填充ViewPager頁面. 你很可能想要使用一個更加具體的實現, 例如:FragmentPagerAdapterorFragmentStatePagerAdapter.

當你實現一個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方法。 2. 解析

 

看上面的翻譯,與我們相關只有這兩段話:

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。

對於上面兩段話,我這裡有兩點要著重講一下:

1、第一段說明了,鍵(Key)的概念,首先這裡要清楚的一點是,每個滑動頁面都對應一個Key,而且這個Key值是用來唯一追蹤這個頁面的,也就是說每個滑動頁面都與一個唯一的Key一一對應。大家先有這個概念就好,關於這個Key是怎麼來的,下面再講。

2、第二段簡單講了一個應用,即將當前頁面本身的View作為Key。其實這個應用就是我們前一章講的例子應用。不太理解?沒關系,下面細講。下面我們講講Key的問題

2.2 詳解KEY

 

instantiateItem (ViewGroup container, int position)

publicObjectinstantiateItem(ViewGroupcontainer, 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),這裡沒必要非要返回視圖本身,也可以這個頁面的其它容器。其實我的理解是可以代表當前頁面的任意值,只要你可以與你增加的View一一對應即可,比如position變量也可以做為Key(最後我們舉個例子試試可不可行)

心得 :

1、從說明中可以看到,在代碼中,我們的責任是將指定position的視圖添加到conatiner中

2、Key的問題:從這個函數就可以看出,該函數返回值就是我們根據參數position增加到conatiner裡的View的所對應的Key!!!!!!!

3、“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)

public abstract booleanisViewFromObject(Viewview,Objectobject)

Determines whether a page View is associated with a specific key object as returned byinstantiateItem(ViewGroup, int). This method is required for a PagerAdapter to function properly.

Parameters
view Page View to check for association withobject object Object to check for association withview
Returns
true ifviewis associated with the key objectobject 功能:該函數用來判斷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。

 

2.3 自定義Key

下面舉個例子來說明Key與View的關系,由於Key與View要一一對應,所以我把每個視圖所處的位置Position作為Key,在上章例子的基礎上更改的,下面先看全部代碼,然後看部分講解:

 

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 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裝入數組中  
        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():

我們在上講也講了在這個函數中Key是作為返回值與當前裝入Container中的視圖對應起來的。所以在這裡我們返回postion與container.addView(viewList.get(position));裡的viewList.get(position)這個視圖對應起來。

 

isViewFromObject():

判斷從instantiateItem()返回來的Key與當前的View是否能對應起來,我們知道從instantiateItem傳過來的其實是position,所以我們要根據position找到View,然後跟參數中的View arg0判斷。

但在真正操作時出現了問題,我們要先將obect對應轉換為int類型:(int)Integer.parseInt(arg1.toString());然後再根據position找到對應的View;

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved