Android零基礎入門第69節:ViewPager快速實現引導頁

   在很多APP第一次啓動時都會出現引導頁,在一些APP裏面還會包括一些左右滑動翻頁和頁面輪播切換的情況。在之前也已經學習了AdapterViewFlipper和ViewFlipper,都可以很好的實現,今天繼續來學習一個功能更加強大的ViewPager組件。

一、ViewPager簡介

    ViewPager是android擴展包v4包中的類,這個類可以讓用戶左右滑動切換當前的view。ViewPager繼承自ViewGroup,也就是ViewPager是一個容器類,可以包含其他的View類。

    ViewPager的主要方法有以下幾個:

  • setAdapter(PagerAdapter adapter) :爲ViewPager設置適配器,ViewPager有三種適配器,包括PagerAdapter、FragmentPagerAdapter、FragmentStatePagerAdapter,它們分別有不同的特性,本期會先來學習PagerAdapter。

  • setCurrentItem(int item) :設置顯示item位置的界面。

  • setOffscreenPageLimit(int limit) :用來設置當前顯示頁面左右兩邊各緩存的頁面數。

  • addOnPageChangeListener(OnPageChangeListener listener) :爲ViewPager添加頁面切換時的監聽。

    關於界面監聽的內容,接下來對OnPageChangeListener中的方法進行說明:

  • onPageScrollStateChanged(int state) :該方法在手指操作屏幕的時候發生變化。有三個值:0(END)、1(PRESS) 、2(UP) 。當用手指滑動翻頁時,手指按下去的時候會觸發這個方法,state值爲1,手指擡起時,如果發生了滑動(即使很小),這個值會變爲2,然後最後變爲0 。總共執行這個方法三次。一種特殊情況是手指按下去以後一點滑動也沒有發生,這個時候只會調用這個方法兩次,state值分別是1、0 。當setCurrentItem翻頁時,會執行這個方法兩次,state值分別爲2 、0 。

  • onPageScrolled(int position, float positionOffset, int positionOffsetPixels) :該方法在滑動過程中將一直被調用,該方法的參數說明如下: 

    • position:當用手指滑動時,如果手指按在頁面上不動,position和當前頁面index是一致的;如果手指向左拖動(相應頁面向右翻動),這時候position大部分時間和當前頁面是一致的,只有翻頁成功的情況下最後一次調用纔會變爲目標頁面;如果手指向右拖動(相應頁面向左翻動),這時候position大部分時間和目標頁面是一致的,只有翻頁不成功的情況下最後一次調用纔會變爲原頁面。當直接設置setCurrentItem翻頁時,如果是相鄰的情況(比如現在是第二個頁面,跳到第一或者第三個頁面),如果頁面向右翻動,大部分時間是和當前頁面是一致的,只有最後才變成目標頁面;如果向左翻動,position和目標頁面是一致的。這和用手指拖動頁面翻動是基本一致的。如果不是相鄰的情況,比如我從第一個頁面跳到第三個頁面,position先是0,然後逐步變成1,然後逐步變成2;我從第三個頁面跳到第一個頁面,position先是1,然後逐步變成0,並沒有出現爲2的情況。 

    • positionOffset:當前頁面滑動比例,如果頁面向右翻動,這個值不斷變大,最後在趨近1的情況後突變爲0。如果頁面向左翻動,這個值不斷變小,最後變爲0。 

    • positionOffsetPixels:當前頁面滑動像素,變化情況和positionOffset一致。

  • onPageSelected(int position) :position是被選中頁面的索引,該方法在頁面被選中或頁面滑動足夠距離切換到該頁手指擡起時調用。

    上面三個方法的執行順序:用手指拖動翻頁時,最先執行一遍onPageScrollStateChanged(1),然後不斷執行onPageScrolled,放手指的時候,直接立即執行一次onPageScrollStateChanged(2),然後立即執行一次onPageSelected,然後再不斷執行onPageScrollStateChanged,最後執行一次onPageScrollStateChanged(0)。

    在大多數使用適配器的控件裏,適配器相對於數據源和視圖來說都更加複雜,同時也決定了這個控件主要的功能,ViewPager也不例外。實現一個PagerAdapter時,至少需要重寫下面的4個方法:

  • getCount():返回有效視圖的數量。

  • isViewFromObject(View, Object):決定一個頁面view是否與instantiateItem(ViewGroup, int)方法返回的具體key對象相關聯。 

  • instantiateItem(ViewGroup, int):創建指定位置的頁面視圖。適配器有責任增加即將創建的View視圖到給定的container中,確保在finishUpdate(viewGroup)返回時,增加視圖的事情已經完成。

  • destroyItem(ViewGroup, int, Object):移除給定位置的view,適配器有責任將該view從container中移除,確保在finishUpdate(viewGroup)返回時,移除視圖的事情已經完成。

    除了上述4個方法,還有以下一些方法,可根據實際需要進行重寫。

  • getItemPosition (Object object):當宿主視圖嘗試判斷一項的位置是否改變時調用。如果給定項的位置沒有改變則返回POSITION_UNCHANGED,如果該項不再存在於適配器中則返回POSITION_NONE。

  • startUpdate (ViewGroup container) :在展示的界面中有改變將要發生時調用。

  • finishUpdate (ViewGroup container):展示界面中的改變完成時調用。在這個時間點上,你必須確保所有的頁面已被合適的從container中添加或移除。

  • notifyDataSetChanged ():該方法由應用程序在適配器數據改變時主動調用。

  • registerDataSetObserver (DataSetObserver observer):註冊一個觀察者去接收關聯到適配器數據變化的回調。

  • unregisterDataSetObserver (DataSetObserver observer):反註冊去接收關聯到適配器數據變化的回調的觀察者。

  • setPrimaryItem (ViewGroup container, int position, Object object):調用該方法去通知當前適配器的哪一項被考慮爲“primary”,它是當前展示給用戶的頁面。

  • getPageTitle (int position):該方法由ViewPager在獲取描述頁面的標題時調用,默認返回null。

  • getPageWidth (int position):該方法返回給定頁面的比例寬度,範圍(0.f-1.f]。

  • saveState ():保存與適配器關聯的實例狀態,噹噹前UI狀態需要重建時恢復。

  • restoreState (Parcelable state, ClassLoader loader):恢復之前由saveState ()保存的與適配器關聯的實例狀態。

    ViewPager的具體使用類似於之前學習的列表類組件,首先構造適配器,然後提供數據源,最後加載適配器。

二、ViewPager示例

    接下來通過一個簡單的示例程序來學習ViewPager的使用。

    繼續使用WidgetSample工程的advancedviewsample模塊,在app/main/res/layout/目錄下創建viewpager_layout.xml文件,在其中填充如下代碼片段:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </android.support.v4.view.ViewPager>
</LinearLayout>

    然後新建幾個頁面文件,第一個頁面命名爲viewpager_pager1.xml,其代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/image_01"/>
</RelativeLayout>

    另外再新建3個,爲了簡單佈局和上面一樣,將其中的代碼加載的圖片換一下即可。

    新建ViewPagerAdapter類,繼承PagerAdapter,並重寫其方法,代碼如下:

package com.jinyu.cqkxzsxy.android.advancedviewsample.adapter;

import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

/**
 * @創建者 鑫鱻
 * @描述 Android零基礎入門到精通系列教程
 * 首發微信公衆號分享達人秀(ShareExpert)
 */
public class ViewPagerAdapter extends PagerAdapter {
    private ArrayList<View> mPageList = null;

    public ViewPagerAdapter(ArrayList<View> pageList) {
        this.mPageList = pageList;
    }

    @Override
    public int getCount() {
        return mPageList.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View pageView = mPageList.get(position);
        container.addView(pageView);
        return pageView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // 將當前位置的View移除
        container.removeView(mPageList.get(position));
    }
}

    新建ViewPagerActivity.java文件,加載上面新建的佈局文件,具體代碼如下:

package com.jinyu.cqkxzsxy.android.advancedviewsample;

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Toast;

import com.jinyu.cqkxzsxy.android.advancedviewsample.adapter.ViewPagerAdapter;

import java.util.ArrayList;

/**
 * @創建者 鑫鱻
 * @描述 Android零基礎入門到精通系列教程,歡迎關注微信公衆號ShareExpert
 */
public class ViewPagerActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
    private ViewPager mViewPager = null;
    private ViewPagerAdapter mAdapter = null;
    private ArrayList<View> mPageList = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.viewpager_layout);

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

        mPageList = new ArrayList<>();
        LayoutInflater inflater = getLayoutInflater();
        mPageList.add(inflater.inflate(R.layout.viewpager_page1, null, false));
        mPageList.add(inflater.inflate(R.layout.viewpager_page2, null, false));
        mPageList.add(inflater.inflate(R.layout.viewpager_page3, null, false));
        mPageList.add(inflater.inflate(R.layout.viewpager_page4, null, false));

        mAdapter = new ViewPagerAdapter(mPageList);
        mViewPager.setAdapter(mAdapter);

        mViewPager.addOnPageChangeListener(this);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        Toast.makeText(this, "第" + (position + 1) + "頁", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

    修改程序啓動的Activity,運行程序,然後左右滑動屏幕,可以看到下圖所示界面效果。

    不知道你是否發現,這是不是就是我們常見的應用程序啓動時的引導頁,只是示例相對來說比較簡單,沒有頁面指示引導,這一塊後續學習再逐步來優化完成。

    今天就先到這裏,如果有問題歡迎留言一起探討,也歡迎加入Android零基礎入門技術討論微信羣,共同成長!

   此文章版權爲微信公衆號分享達人秀(ShareExpert)——鑫鱻所有,若需轉載請聯繫作者授權,特此聲明!

往期總結分享:

Android零基礎入門第1節:Android的前世今生

Android零基礎入門第2節:Android 系統架構和應用組件那些事

Android零基礎入門第3節:帶你一起來聊一聊Android開發環境

Android零基礎入門第4節:正確安裝和配置JDK, 高富帥養成第一招

Android零基礎入門第5節:善用ADT Bundle, 輕鬆邂逅女神

Android零基礎入門第6節:配置優化SDK Manager, 正式約會女神

Android零基礎入門第7節:搞定Android模擬器,開啓甜蜜之旅

Android零基礎入門第8節:HelloWorld,我的第一趟旅程出發點

Android零基礎入門第9節:Android應用實戰,不懂代碼也可以開發

Android零基礎入門第10節:開發IDE大升級,終於迎來了Android Studio

Android零基礎入門第11節:簡單幾步帶你飛,運行Android Studio工程

Android零基礎入門第12節:熟悉Android Studio界面,開始裝逼賣萌

Android零基礎入門第13節:Android Studio個性化配置,打造開發利器

Android零基礎入門第14節:使用高速Genymotion,跨入火箭時代

Android零基礎入門第15節:掌握Android Studio項目結構,揚帆起航

Android零基礎入門第16節:Android用戶界面開發概述

Android零基礎入門第17節:文本框TextView

Android零基礎入門第18節:輸入框EditText

Android零基礎入門第19節:按鈕Button

Android零基礎入門第20節:複選框CheckBox和單選按鈕RadioButton

Android零基礎入門第21節:開關組件ToggleButton和Switch

Android零基礎入門第22節:圖像視圖ImageView

Android零基礎入門第23節:圖像按鈕ImageButton和縮放按鈕ZoomButton

Android零基礎入門第24節:自定義View簡單使用,打造屬於你的控件

Android零基礎入門第25節:簡單且最常用的LinearLayout線性佈局

Android零基礎入門第26節:兩種對齊方式,layout_gravity和gravity大不同

Android零基礎入門第27節:正確使用padding和margin

Android零基礎入門第28節:輕鬆掌握RelativeLayout相對佈局

Android零基礎入門第29節:善用TableLayout表格佈局

Android零基礎入門第30節:兩分鐘掌握FrameLayout幀佈局

Android零基礎入門第31節:少用的AbsoluteLayout絕對佈局

Android零基礎入門第32節:新推出的GridLayout網格佈局

Android零基礎入門第33節:Android事件處理概述

Android零基礎入門第34節:Android中基於監聽的事件處理

Android零基礎入門第35節:Android中基於回調的事件處理

Android零基礎入門第36節:Android系統事件的處理

Android零基礎入門第37節:初識ListView

Android零基礎入門第38節:初識Adapter

Android零基礎入門第39節:ListActivity和自定義列表項

Android零基礎入門第40節:自定義ArrayAdapter

Android零基礎入門第41節:使用SimpleAdapter

Android零基礎入門第42節:自定義BaseAdapter

Android零基礎入門第43節:ListView優化和列表首尾使用

Android零基礎入門第44節:ListView數據動態更新

Android零基礎入門第45節:網格視圖GridView

Android零基礎入門第46節:列表選項框Spinner

Android零基礎入門第47節:自動完成文本框AutoCompleteTextView

Android零基礎入門第48節:可摺疊列表ExpandableListView

Android零基礎入門第49節:AdapterViewFlipper圖片輪播

Android零基礎入門第50節:StackView卡片堆疊

Android零基礎入門第51節:進度條ProgressBar

Android零基礎入門第52節:自定義ProgressBar炫酷進度條

Android零基礎入門第53節:拖動條SeekBar和星級評分條RatingBar

Android零基礎入門第54節:視圖切換組件ViewSwitcher

Android零基礎入門第55節:ImageSwitcher和TextSwitcher

Android零基礎入門第56節:翻轉視圖ViewFlipper

Android零基礎入門第57節:DatePicker和TimePicker選擇器

Android零基礎入門第58節:數值選擇器NumberPicker

Android零基礎入門第59節:常用三大Clock時鐘組件

Android零基礎入門第60節:日曆視圖CalendarView和定時器Chronometer

Android零基礎入門第61節:滾動視圖ScrollView

Android零基礎入門第62節:搜索框組件SearchView

Android零基礎入門第63節:值得借鑑學習的選項卡TabHost

Android零基礎入門第64節:揭開RecyclerView廬山真面目

Android零基礎入門第65節:RecyclerView分割線開發技巧

Android零基礎入門第66節:RecyclerView點擊事件處理

Android零基礎入門第67節:RecyclerView數據動態更新

Android零基礎入門第68節:RecyclerView添加首尾視圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章