在不少APP第一次啓動時都會出現引導頁,在一些APP裏面還會包括一些左右滑動翻頁和頁面輪播切換的狀況。在以前也已經學習了AdapterViewFlipper和ViewFlipper,均可以很好的實現,今天繼續來學習一個功能更增強大的ViewPager組件。java
ViewPager是android擴展包v4包中的類,這個類可讓用戶左右滑動切換當前的view。ViewPager繼承自ViewGroup,也就是ViewPager是一個容器類,能夠包含其餘的View類。android
ViewPager的主要方法有如下幾個:緩存
setAdapter(PagerAdapter adapter) :爲ViewPager設置適配器,ViewPager有三種適配器,包括PagerAdapter、FragmentPagerAdapter、FragmentStatePagerAdapter,它們分別有不一樣的特性,本期會先來學習PagerAdapter。微信
setCurrentItem(int item) :設置顯示item位置的界面。架構
setOffscreenPageLimit(int limit) :用來設置當前顯示頁面左右兩邊各緩存的頁面數。app
addOnPageChangeListener(OnPageChangeListener listener) :爲ViewPager添加頁面切換時的監聽。ide
關於界面監聽的內容,接下來對OnPageChangeListener中的方法進行說明:佈局
onPageScrollStateChanged(int state) :該方法在手指操做屏幕的時候發生變化。有三個值:0(END)、1(PRESS) 、2(UP) 。當用手指滑動翻頁時,手指按下去的時候會觸發這個方法,state值爲1,手指擡起時,若是發生了滑動(即便很小),這個值會變爲2,而後最後變爲0 。總共執行這個方法三次。一種特殊狀況是手指按下去之後一點滑動也沒有發生,這個時候只會調用這個方法兩次,state值分別是一、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的使用。
繼續使用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添加首尾視圖