ViewPager
一般來說在Android開發(fā)中ViewPager的運(yùn)用還算比較常見澈吨,比如說Android手機(jī)微信的界面之前的左右滑動(dòng)的功能穷娱,還有比如說淘寶上廣告圖片的輪播效果恬涧。都是可以用ViewPager來實(shí)現(xiàn)和完成云芦。
ViewPager繼承自ViewGroup虚汛,也就是ViewPager是一個(gè)容器類拟赊,可以包含其他的View類。?是一個(gè)允許使用者左右滑動(dòng)數(shù)據(jù)頁面的布局管理器草慧。你可以通過一個(gè)適配器(PagerAdapter)來管理要顯示的頁面桶蛔。
PagerAdapter是用于“將多個(gè)頁面填充到ViewPager”的適配器的一個(gè)基類,大多數(shù)情況下漫谷,你們可能更傾向于使用一個(gè)實(shí)現(xiàn)了PagerAdapter并且更加具體的適配器
要通過自己寫的一個(gè)適配器來繼承PagerAdapter的仔雷,其中有四個(gè)方法是必須重寫的。
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == arg1;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(list.get(position));
return list.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
container.removeView(list.get(position));
}
1,getCount() // 獲取要滑動(dòng)的控件的數(shù)量碟婆。?
2电抚,isViewFromObject(View, Object) // 來判斷顯示的是否是同一張圖片,這里我們將兩個(gè)參數(shù)相比較返回即可
接下來的兩個(gè)方法是需要手動(dòng)來添加到適配器中的竖共。
3蝙叛,instantiateItem(ViewGroup, int) // 當(dāng)要顯示的圖片可以進(jìn)行緩存的時(shí)候,會(huì)調(diào)用這個(gè)方法進(jìn)行顯示圖片的初始化公给,我們將要顯示的ImageView加入到ViewGroup中借帘,然后作為返回值返回即可
4,destroyItem(ViewGroup, int, Object) // PagerAdapter只緩存三張要顯示的圖片淌铐,如果滑動(dòng)的圖片超出了緩存的范圍肺然,就會(huì)調(diào)用這個(gè)方法,將圖片銷毀
在創(chuàng)建適配器的同時(shí)也要在適配器創(chuàng)建一個(gè)構(gòu)造方法(構(gòu)造方法的參數(shù)是根據(jù)要傳的數(shù)據(jù)內(nèi)容來給定的)
然后在你的Activity中調(diào)用適配器就OK了腿准。
viewpager不直接處理每一個(gè)視圖而是將各個(gè)視圖與一個(gè)鍵聯(lián)系起來际起。這個(gè)鍵用來跟蹤且唯一代表一個(gè)頁面,不僅如此吐葱,該鍵還獨(dú)立于這個(gè)頁面所在adapter的位置街望。當(dāng)pageradapter將要改變的時(shí)候他會(huì)調(diào)用startUpdate函數(shù),接下來會(huì)調(diào)用一次或多次的instantiateItem或者destroyItem唇撬。最后在更新的后期會(huì)調(diào)用finishUpdate。當(dāng)finishUpdate返回時(shí) instantiateItem返回的對象應(yīng)該添加到父ViewGroup destroyItem返回的對象應(yīng)該被ViewGroup刪除展融。
isViewFromObject(View, Object)代表了當(dāng)前的頁面是否與給定的鍵相關(guān)聯(lián)窖认。
isViewFromObject
功能:該函數(shù)用來判斷instantiateItem(ViewGroup, int)函數(shù)所返回來的Key與一個(gè)頁面視圖是否是代表的同一個(gè)視圖(即它倆是否是對應(yīng)的,對應(yīng)的表示同一個(gè)View)
返回值:如果對應(yīng)的是同一個(gè)View告希,返回True扑浸,否則返回False。
還有沒有結(jié)束燕偶,這才剛剛開始喝噪,接下來處理ViewPager滑動(dòng)的事件;
給ViewPager設(shè)置監(jiān)聽的接口是OnPageChangeListener指么。當(dāng)去實(shí)現(xiàn)這個(gè)接口的時(shí)候回重寫其中的一下方法:
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
}
現(xiàn)在我們是做簡單的微信滑動(dòng)的功能的話酝惧,只需要在onPageSelected()中添加滑動(dòng)事件就可以。
簡單說一下上述三種方法的作用
onPageScrollStateChanged(int arg0) 伯诬,此方法是在狀態(tài)改變的時(shí)候調(diào)用晚唇,其中arg0這個(gè)參數(shù)
有三種狀態(tài)(0,1盗似,2)哩陕。arg0 ==1的正在滑動(dòng),arg0==2的滑動(dòng)完畢了,arg0==0的什么都沒做悍及。
當(dāng)頁面開始滑動(dòng)的時(shí)候闽瓢,三種狀態(tài)的變化順序?yàn)椋?,2心赶,0)
onPageScrolled(int arg0,float arg1,int arg2) 扣讼,當(dāng)頁面在滑動(dòng)的時(shí)候會(huì)調(diào)用此方法,在滑動(dòng)被停止之前园担,此方法回一直得到
調(diào)用届谈。其中三個(gè)參數(shù)的含義分別為:
arg0 :當(dāng)前頁面,及你點(diǎn)擊滑動(dòng)的頁面
arg1:當(dāng)前頁面偏移的百分比
arg2:當(dāng)前頁面偏移的像素位置
onPageSelected(int arg0) : 此方法是頁面跳轉(zhuǎn)完后得到調(diào)用弯汰,arg0是你當(dāng)前選中的頁面的Position(位置編號)艰山。
ViewPager更多的時(shí)候會(huì)與Fragment一起使用。Android提供了一些專門的適配器來讓ViewPager與Fragment一起工作咏闪,也就是FragmentPagerAdapter與FragmentStatePagerAdapter曙搬。他們基本上可以滿足大部分常見的需求?
在大部分時(shí)候,項(xiàng)目中的ViewPager會(huì)和Fragment同時(shí)出現(xiàn)鸽嫂,每一個(gè)ViewPager的頁面就是一個(gè)Fragment(微信主頁)?Android提供了一些專門的適配器來讓ViewPager與Fragment一起工作纵装,也就是FragmentPagerAdapter與FragmentStatePagerAdapter。
FragmentPagerAdapter繼承自PagerAdapter 据某,主要用來展示多個(gè)Fragment頁面橡娄,并且每一個(gè)Fragment都會(huì)被保存在fragment manager中。
FragmentPagerAdapter最適用于那種少量且相對靜態(tài)的頁面癣籽,例如幾個(gè)tab頁挽唉。每一個(gè)用戶訪問過的fragment都會(huì)被保存在內(nèi)存中對于較多的頁面集合,更推薦使用FragmentStatePagerAdapter筷狼。
FragmentStatePagerAdapter繼承自PagerAdapter瓶籽,主要使用Fragment來管理每個(gè)頁面。這個(gè)類同樣用來保存和恢復(fù)fragment頁面的狀態(tài)埂材。
FragmentStatePagerAdapter更多用于大量頁面塑顺,例如視圖列表。當(dāng)某個(gè)頁面對用戶不再可見時(shí)俏险,他們的整個(gè)fragment就會(huì)被銷毀严拒,僅保留fragment狀態(tài)。相比于FragmentPagerAdapter竖独,這樣做的好處是在訪問各個(gè)頁面時(shí)能節(jié)約大量的內(nèi)存開銷糙俗,但代價(jià)是在頁面切換時(shí)會(huì)增加非常多的開銷。
FragmentPagerAdapter與FragmentStatePagerAdapter存在著大量相似之處预鬓,用法也差不多巧骚,他們之間最大的不同在于:用戶訪問過的頁面不可見之后是否會(huì)保留在內(nèi)存中赊颠,而這個(gè)區(qū)別也構(gòu)成了他們使用場景的不同。
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class SplashActivity extends Activity {
boolean isFirstIn = false;
private static final int GO_HOME = 1000;
private static final int GO_GUIDE = 1001;
// 延遲3秒
private static final long SPLASH_DELAY_MILLIS = 3000;
private static final String SHAREDPREFERENCES_NAME = "first_pref";
/**
* Handler:跳轉(zhuǎn)到不同界面
*/
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case GO_HOME:
goHome();
break;
case GO_GUIDE:
goGuide();
break;
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
init();
}
private void init() {
// 讀取SharedPreferences中需要的數(shù)據(jù)
// 使用SharedPreferences來記錄程序的使用次數(shù)
SharedPreferences preferences = getSharedPreferences(
SHAREDPREFERENCES_NAME, MODE_PRIVATE);
// 取得相應(yīng)的值劈彪,如果沒有該值竣蹦,說明還未寫入,用true作為默認(rèn)值
isFirstIn = preferences.getBoolean("isFirstIn", true);
// 判斷程序與第幾次運(yùn)行沧奴,如果是第一次運(yùn)行則跳轉(zhuǎn)到引導(dǎo)界面痘括,否則跳轉(zhuǎn)到主界面
if (!isFirstIn) {
// 使用Handler的postDelayed方法,3秒后執(zhí)行跳轉(zhuǎn)到MainActivity
mHandler.sendEmptyMessageDelayed(GO_HOME, SPLASH_DELAY_MILLIS);
} else {
mHandler.sendEmptyMessageDelayed(GO_GUIDE, SPLASH_DELAY_MILLIS);
}
}
private void goHome() {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
SplashActivity.this.startActivity(intent);
SplashActivity.this.finish();
}
private void goGuide() {
Intent intent = new Intent(SplashActivity.this, GuideActivity.class);
SplashActivity.this.startActivity(intent);
SplashActivity.this.finish();
}
}
GuideActivity.java引導(dǎo)界面
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import cn.eoe.leigo.splash.adapter.ViewPagerAdapter;
public class GuideActivity extends Activity implements OnPageChangeListener {
private ViewPager vp;
private ViewPagerAdapter vpAdapter;
private List<View> views;
// 底部小點(diǎn)圖片
private ImageView[] dots;
// 記錄當(dāng)前選中位置
private int currentIndex;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.guide);
// 初始化頁面
initViews();
// 初始化底部小點(diǎn)
initDots();
}
private void initViews() {
LayoutInflater inflater = LayoutInflater.from(this);
views = new ArrayList<View>();
// 初始化引導(dǎo)圖片列表
views.add(inflater.inflate(R.layout.what_new_one, null));
views.add(inflater.inflate(R.layout.what_new_two, null));
views.add(inflater.inflate(R.layout.what_new_three, null));
views.add(inflater.inflate(R.layout.what_new_four, null));
// 初始化Adapter
vpAdapter = new ViewPagerAdapter(views, this);
vp = (ViewPager) findViewById(R.id.viewpager);
vp.setAdapter(vpAdapter);
// 綁定回調(diào)
vp.setOnPageChangeListener(this);
}
private void initDots() {
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
dots = new ImageView[views.size()];
// 循環(huán)取得小點(diǎn)圖片
for (int i = 0; i < views.size(); i++) {
dots[i] = (ImageView) ll.getChildAt(i);
dots[i].setEnabled(true);// 都設(shè)為灰色
}
currentIndex = 0;
dots[currentIndex].setEnabled(false);// 設(shè)置為白色滔吠,即選中狀態(tài)
}
private void setCurrentDot(int position) {
if (position < 0 || position > views.size() - 1
|| currentIndex == position) {
return;
}
dots[position].setEnabled(false);
dots[currentIndex].setEnabled(true);
currentIndex = position;
}
// 當(dāng)滑動(dòng)狀態(tài)改變時(shí)調(diào)用
@Override
public void onPageScrollStateChanged(int arg0) {
}
// 當(dāng)當(dāng)前頁面被滑動(dòng)時(shí)調(diào)用
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
// 當(dāng)新的頁面被選中時(shí)調(diào)用
@Override
public void onPageSelected(int arg0) {
// 設(shè)置底部小點(diǎn)選中狀態(tài)
setCurrentDot(arg0);
}
}
ViewPagerAdapter.java纲菌。ViewPager的適配器
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import cn.eoe.leigo.splash.MainActivity;
import cn.eoe.leigo.splash.R;
/**
*/
public class ViewPagerAdapter extends PagerAdapter {
// 界面列表
private List<View> views;
private Activity activity;
private static final String SHAREDPREFERENCES_NAME = "first_pref";
public ViewPagerAdapter(List<View> views, Activity activity) {
this.views = views;
this.activity = activity;
}
// 銷毀arg1位置的界面
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView(views.get(arg1));
}
@Override
public void finishUpdate(View arg0) {
}
// 獲得當(dāng)前界面數(shù)
@Override
public int getCount() {
if (views != null) {
return views.size();
}
return 0;
}
// 初始化arg1位置的界面
@Override
public Object instantiateItem(View arg0, int arg1) {
((ViewPager) arg0).addView(views.get(arg1), 0);
if (arg1 == views.size() - 1) {
ImageView mStartWeiboImageButton = (ImageView) arg0
.findViewById(R.id.iv_start_weibo);
mStartWeiboImageButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 設(shè)置已經(jīng)引導(dǎo)
setGuided();
goHome();
}
});
}
return views.get(arg1);
}
private void goHome() {
// 跳轉(zhuǎn)
Intent intent = new Intent(activity, MainActivity.class);
activity.startActivity(intent);
activity.finish();
}
/**
*
* method desc:設(shè)置已經(jīng)引導(dǎo)過了,下次啟動(dòng)不用再次引導(dǎo)
*/
private void setGuided() {
SharedPreferences preferences = activity.getSharedPreferences(
SHAREDPREFERENCES_NAME, Context.MODE_PRIVATE);
Editor editor = preferences.edit();
// 存入數(shù)據(jù)
editor.putBoolean("isFirstIn", false);
// 提交修改
editor.commit();
}
// 判斷是否由對象生成界面
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return (arg0 == arg1);
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void startUpdate(View arg0) {
}
}
至于MainActivity隨便了疮绷。
效果就是如下圖片
所以總結(jié)一下翰舌,我們可以使用ViewPager做什么:
1.程序使用導(dǎo)航,外加底部圓點(diǎn)的效果冬骚,這個(gè)在微信示例里介紹了
2.頁卡滑動(dòng)椅贱,加上菜單的效果,不管是之前的支持手勢也支持底部圖標(biāo)點(diǎn)擊的微信只冻,還是今天的微博庇麦。
相互學(xué)習(xí),共同努力喜德!
微信號:romance-l