ViewPager 使用

學習了 ViewPager俊柔,在此做個總結,主要包括一下幾個方面:

  • ViewPager 簡介
  • ViewPager 的使用
  • FragmentStatePagerAdapter 和 FragmentPagerAdapter
  • ViewPager 的工作原理
  • 恢復 CrimeFragment 的邊距
  • 添加 Jump to First 按鈕和 Jump to Last 按鈕

ViewPager 簡介

  1. ViewPager 是 android 擴展包 v4 包中的類,這個類可以讓用戶左右切換當前的 view
  2. ViewPager 直接繼承了 ViewGroup降传,所有它是一個容器類,可以在其中添加其他的 view 類。
  3. ViewPager 需要一個 PagerAdapter 適配器類給它提供數(shù)據(jù)搀暑。
  4. ViewPager 經(jīng)常和 Fragment 一起使用,并且提供了專門的 FragmentPagerAdapter 和 FragmentStatePagerAdapter 類供 Fragment 中的 ViewPager 使用跨琳。

ViewPager 的使用

因為之前的封裝自点,CrimeFragment 類可以不做修改直接使用。接下來看我們需要完成的任務脉让。

  1. 創(chuàng)建 CrimePagerActivity 類
  2. 在 CrimePagerActivity 類中關聯(lián)使用 ViewPager 及其 Adapter
  3. 修改 CrimeHolder.onClick(...) 方法桂敛,轉而啟動 CrimePagerActivity

創(chuàng)建 CrimePagerActivity 類

CrimePagerActivity.java

public class CrimePagerActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crime_pager);
    }

布局文件

activity_crime_pager.xml

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/crime_view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CrimePagerActivity">
</android.support.v4.view.ViewPager>

在 CrimePagerActivity 類中關聯(lián)使用 ViewPager 及其 Adapter

ViewPager 某種程度上與 RecyclerView 類似,都需要借助 Adapter 提供視圖溅潜。因為 ViewPager 與 PagerAdapter 間的配合要復雜很多术唬,這里先用 FragmentPagerAdapter,它能處理很多細節(jié)的問題

FragmentPagerAdapter 提供了兩個有用的方法:getCount() 和 getItem(int)滚澜。調用 getItem(int) 方法粗仓,獲取并顯示 crime 數(shù)組中指定位置的 Crime 時,它會返回配置過的 CrimeFragment 來顯示指定的 Crime设捐。
CrimePagerActivity.java

public class CrimePagerActivity extends AppCompatActivity {

    private ViewPager mViewPager;
    private List<Crime> mCrimes;
    
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crime_pager);

        mViewPager = (ViewPager) findViewById(R.id.crime_view_pager);

        mCrimes  =CrimeLab.get(this).getCrimes();
        FragmentManager fragmentManager = getSupportFragmentManager();
        mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
            @Override
            public Fragment getItem(int position) {
                Crime crime = mCrimes.get(position);
                return CrimeFragment.newInstance(crime.getId());
            }
            @Override
            public int getCount() {
                return mCrimes.size();
            }
        });

解釋一下上面的代碼借浊,在 activity 視圖中找到 ViewPager 后,我們從 CrimeLab 獲取數(shù)據(jù)集萝招,然后獲取 FragmentManager 的實例蚂斤。接下來,設置 adapter 為 FragmentStatePagerAdapter 的一個匿名實例槐沼。創(chuàng)建 FragmentStatePagerAdapter 需要 FragmentManager曙蒸。如前所述,qiansuoshuFragmentStatePagerAdapter 是我們的代理岗钩,代理首先將 getItem(int) 方法返回的 fragment 添加給 activity纽窟,然后才能使用 fragment 完成自己的工作。

代理究竟做了哪些工作呢兼吓?簡單來說就是將返回的 fragment 添加給托管 activity师倔,并幫助 ViewPager 找到 fragment 的視圖一一對應。getItem(int) 方法首先獲取指定位置的 Crime 實例周蹭,然后利用該 Crime 實例的 ID 創(chuàng)建并返回一個經(jīng)過有效配置發(fā) CrimeFragment趋艘。

修改 CrimeHolder.onClick(...) 方法,轉而啟動 CrimePagerActivity

CrimePagerActivity.java

 private static final String EXTRA_CRIME_ID = "com.bignerdranch.android.criminalintent.crime_id";

    private ViewPager mViewPager;
    private List<Crime> mCrimes;

    public static Intent newIntent(Context packageContext, UUID crimeId){
        Intent intent = new Intent(packageContext,CrimePagerActivity.class);
        intent.putExtra(EXTRA_CRIME_ID,crimeId);
        return intent;
    }
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crime_pager);
        
        UUID crimeId = (UUID)getIntent().getSerializableExtra(EXTRA_CRIME_ID) ;
        ...
    }

修改 CrimeHolder.onClick(...) 方法凶朗,轉而啟動 CrimePagerActivity

CrimePagerActivity.java

    @Override
    public void onClick(View view) {
       // Intent intent = CrimeActivity.newIntent(getActivity(),mCrime.getId());
        Intent intent = CrimePagerActivity.newIntent(getActivity(),mCrime.getId());
        mPosition = this.getAdapterPosition();
        startActivity(intent);
    }

最后在 AndroidManifest.xml中刪除 CrimeActivity 的代碼瓷胧。

注意,目前 ViewPager 還不完美棚愤,ViewPager 默認只顯示 PagerAdapter 中的第一個列表項搓萧。要顯示選中的列表項需要在 CrimePagerActivity.onCreate(Bundle) 末尾添加以下代碼杂数。

CrimePagerActivity.java


for (int i = 0; i < mCrimes.size(); i++){
    if (mCrimes.get(i).getId().equals(crimeId)){
        mViewPager.setCurrentItem(i);
        break;
    }
}

FragmentStatePagerAdapter 和 FragmentPagerAdapter

FragmentPagerAdapter 是另一種可用的 PagerAdapter,其用法和 FragmentStatePagerAdapter 基本一致瘸洛,只是在卸載不需要的 fragment 時揍移,各自采用的處理方法不同。

FragmentStatePagerAdapter 會銷毀不需要的 fragment反肋,而 FragmentPagerAdapter 是調用 detach(Fragment) 方法來處理它那伐,只是銷毀了 fragment 的視圖,而 fragment 的實例由 FragmentManager 維護石蔗,因此罕邀,F(xiàn)ragmentPagerAdapter 創(chuàng)建的 fragment 永遠不會被銷毀。

所以當數(shù)據(jù)量大時养距,可以選擇 FragmentStatePagerAdapter诉探,用戶界面只有少量固定的 fragment 時,可以選擇 FragmentPagerAdapter棍厌。

ViewPager 的工作原理

首先明確一點肾胯,要實現(xiàn)自己的 PagerAdapter 接口時,就需要了解它的工作原理耘纱,那么什么時候需要實現(xiàn) PagerAdapter 接口呢敬肚?當需要托管非 fragment 視圖時(如圖片),就需要實現(xiàn)原生的 PagerAdapter揣炕。

為什么使用 ViewPager而不是 RecyclerView?

Adapter 需要我們及時提供 View东跪。然而畸陡,覺得 fragment 創(chuàng)建的是 FragmentManager。因此虽填,當 RecyclerView 要求 Adapter 提供 fragment 視圖時丁恭。我們無法立即創(chuàng)建 fragment 并提供其視圖。這就是 PagerView 存在的理由斋日。

下面看它的內部實現(xiàn)牲览。

PagerAdapter 不使用可返回視圖的 onBindViewHolder(...) 方法,而是使用以下方法:

public Object instantiateItem(ViewGroup container,int position)
public void destroyItem(ViewGroup container,int position,Object object) 
public abstract boolean isViewFromObject(View view,Object object)

instantiateItem(ViewGroup,int) 方法是告訴 pager adapter 創(chuàng)建指定位置的列表項視圖恶守,但并不要求立即創(chuàng)建視圖第献,pager adpter 可以自己決定何時創(chuàng)建視圖。然后將其添加給 ViewGroup兔港,而 destroyItem(ViewGroup,int,Object) 方法則是告訴 pager adapter 視圖已經(jīng)銷毀(FragmentStatePagerAdapter 和 FragmentPagerAdapter 的不同主要是在這里)庸毫。

詳情可以參考此鏈接:
ViewPager 全面剖析及使用詳解

視圖創(chuàng)建后,ViewPager 會在某個時間點看到它衫樊,為了確定該視圖所屬的對象飒赃,ViewPager 會調用 isViewFromObject(View,Object)利花,這里的 object 是 instantiateItem(ViewGroup,int) 方法返回的對象。

恢復 CrimeFragment 的邊距

把 fragment_crime.xml 下的 LinearLayout 的 android:layout_margin="16dp" 改成 android:padding="16dp"载佳。

GitHub地址

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末炒事,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蔫慧,更是在濱河造成了極大的恐慌挠乳,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藕漱,死亡現(xiàn)場離奇詭異欲侮,居然都是意外死亡,警方通過查閱死者的電腦和手機肋联,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門威蕉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人橄仍,你說我怎么就攤上這事韧涨。” “怎么了侮繁?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵虑粥,是天一觀的道長。 經(jīng)常有香客問我宪哩,道長娩贷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任锁孟,我火速辦了婚禮彬祖,結果婚禮上,老公的妹妹穿的比我還像新娘品抽。我一直安慰自己储笑,他們只是感情好,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布圆恤。 她就那樣靜靜地躺著突倍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盆昙。 梳的紋絲不亂的頭發(fā)上羽历,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機與錄音淡喜,去河邊找鬼窄陡。 笑死,一個胖子當著我的面吹牛拆火,可吹牛的內容都是我干的跳夭。 我是一名探鬼主播涂圆,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼币叹!你這毒婦竟也來了润歉?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤颈抚,失蹤者是張志新(化名)和其女友劉穎踩衩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贩汉,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡驱富,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了匹舞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褐鸥。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赐稽,靈堂內的尸體忽然破棺而出叫榕,到底是詐尸還是另有隱情,我是刑警寧澤姊舵,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布晰绎,位于F島的核電站,受9級特大地震影響括丁,放射性物質發(fā)生泄漏荞下。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一史飞、第九天 我趴在偏房一處隱蔽的房頂上張望尖昏。 院中可真熱鬧,春花似錦祸憋、人聲如沸会宪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至塞帐,卻和暖如春拦赠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背葵姥。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工荷鼠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人榔幸。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓允乐,卻偏偏與公主長得像矮嫉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子牍疏,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內容