ViewPager
一般來說在Android開發中ViewPager的運用還算比較常見,比如說Android手機微信的界面之前的左右滑動的功能,還有比如說淘寶上廣告圖片的輪播效果。都是可以用ViewPager來實現和完成。
ViewPager繼承自ViewGroup,也就是ViewPager是一個容器類,可以包含其他的View類。?是一個允許使用者左右滑動數據頁面的布局管理器。你可以通過一個適配器(PagerAdapter)來管理要顯示的頁面。
PagerAdapter是用于“將多個頁面填充到ViewPager”的適配器的一個基類,大多數情況下,你們可能更傾向于使用一個實現了PagerAdapter并且更加具體的適配器
要通過自己寫的一個適配器來繼承PagerAdapter的,其中有四個方法是必須重寫的。
@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() // 獲取要滑動的控件的數量。?
2,isViewFromObject(View, Object) // 來判斷顯示的是否是同一張圖片,這里我們將兩個參數相比較返回即可
接下來的兩個方法是需要手動來添加到適配器中的。
3,instantiateItem(ViewGroup, int) // 當要顯示的圖片可以進行緩存的時候,會調用這個方法進行顯示圖片的初始化,我們將要顯示的ImageView加入到ViewGroup中,然后作為返回值返回即可
4,destroyItem(ViewGroup, int, Object) // PagerAdapter只緩存三張要顯示的圖片,如果滑動的圖片超出了緩存的范圍,就會調用這個方法,將圖片銷毀
在創建適配器的同時也要在適配器創建一個構造方法(構造方法的參數是根據要傳的數據內容來給定的)
然后在你的Activity中調用適配器就OK了。
viewpager不直接處理每一個視圖而是將各個視圖與一個鍵聯系起來。這個鍵用來跟蹤且唯一代表一個頁面,不僅如此,該鍵還獨立于這個頁面所在adapter的位置。當pageradapter將要改變的時候他會調用startUpdate函數,接下來會調用一次或多次的instantiateItem或者destroyItem。最后在更新的后期會調用finishUpdate。當finishUpdate返回時 instantiateItem返回的對象應該添加到父ViewGroup destroyItem返回的對象應該被ViewGroup刪除。
isViewFromObject(View, Object)代表了當前的頁面是否與給定的鍵相關聯。
isViewFromObject
功能:該函數用來判斷instantiateItem(ViewGroup, int)函數所返回來的Key與一個頁面視圖是否是代表的同一個視圖(即它倆是否是對應的,對應的表示同一個View)
返回值:如果對應的是同一個View,返回True,否則返回False。
還有沒有結束,這才剛剛開始,接下來處理ViewPager滑動的事件;
給ViewPager設置監聽的接口是OnPageChangeListener。當去實現這個接口的時候回重寫其中的一下方法:
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
}
現在我們是做簡單的微信滑動的功能的話,只需要在onPageSelected()中添加滑動事件就可以。
簡單說一下上述三種方法的作用
onPageScrollStateChanged(int arg0) ,此方法是在狀態改變的時候調用,其中arg0這個參數
有三種狀態(0,1,2)。arg0 ==1的正在滑動,arg0==2的滑動完畢了,arg0==0的什么都沒做。
當頁面開始滑動的時候,三種狀態的變化順序為(1,2,0)
onPageScrolled(int arg0,float arg1,int arg2) ,當頁面在滑動的時候會調用此方法,在滑動被停止之前,此方法回一直得到
調用。其中三個參數的含義分別為:
arg0 :當前頁面,及你點擊滑動的頁面
arg1:當前頁面偏移的百分比
arg2:當前頁面偏移的像素位置
onPageSelected(int arg0) : 此方法是頁面跳轉完后得到調用,arg0是你當前選中的頁面的Position(位置編號)。
ViewPager更多的時候會與Fragment一起使用。Android提供了一些專門的適配器來讓ViewPager與Fragment一起工作,也就是FragmentPagerAdapter與FragmentStatePagerAdapter。他們基本上可以滿足大部分常見的需求?
在大部分時候,項目中的ViewPager會和Fragment同時出現,每一個ViewPager的頁面就是一個Fragment(微信主頁)?Android提供了一些專門的適配器來讓ViewPager與Fragment一起工作,也就是FragmentPagerAdapter與FragmentStatePagerAdapter。
FragmentPagerAdapter繼承自PagerAdapter ,主要用來展示多個Fragment頁面,并且每一個Fragment都會被保存在fragment manager中。
FragmentPagerAdapter最適用于那種少量且相對靜態的頁面,例如幾個tab頁。每一個用戶訪問過的fragment都會被保存在內存中對于較多的頁面集合,更推薦使用FragmentStatePagerAdapter。
FragmentStatePagerAdapter繼承自PagerAdapter,主要使用Fragment來管理每個頁面。這個類同樣用來保存和恢復fragment頁面的狀態。
FragmentStatePagerAdapter更多用于大量頁面,例如視圖列表。當某個頁面對用戶不再可見時,他們的整個fragment就會被銷毀,僅保留fragment狀態。相比于FragmentPagerAdapter,這樣做的好處是在訪問各個頁面時能節約大量的內存開銷,但代價是在頁面切換時會增加非常多的開銷。
FragmentPagerAdapter與FragmentStatePagerAdapter存在著大量相似之處,用法也差不多,他們之間最大的不同在于:用戶訪問過的頁面不可見之后是否會保留在內存中,而這個區別也構成了他們使用場景的不同。
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:跳轉到不同界面
*/
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中需要的數據
// 使用SharedPreferences來記錄程序的使用次數
SharedPreferences preferences = getSharedPreferences(
SHAREDPREFERENCES_NAME, MODE_PRIVATE);
// 取得相應的值,如果沒有該值,說明還未寫入,用true作為默認值
isFirstIn = preferences.getBoolean("isFirstIn", true);
// 判斷程序與第幾次運行,如果是第一次運行則跳轉到引導界面,否則跳轉到主界面
if (!isFirstIn) {
// 使用Handler的postDelayed方法,3秒后執行跳轉到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引導界面
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;
// 底部小點圖片
private ImageView[] dots;
// 記錄當前選中位置
private int currentIndex;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.guide);
// 初始化頁面
initViews();
// 初始化底部小點
initDots();
}
private void initViews() {
LayoutInflater inflater = LayoutInflater.from(this);
views = new ArrayList<View>();
// 初始化引導圖片列表
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);
// 綁定回調
vp.setOnPageChangeListener(this);
}
private void initDots() {
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
dots = new ImageView[views.size()];
// 循環取得小點圖片
for (int i = 0; i < views.size(); i++) {
dots[i] = (ImageView) ll.getChildAt(i);
dots[i].setEnabled(true);// 都設為灰色
}
currentIndex = 0;
dots[currentIndex].setEnabled(false);// 設置為白色,即選中狀態
}
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;
}
// 當滑動狀態改變時調用
@Override
public void onPageScrollStateChanged(int arg0) {
}
// 當當前頁面被滑動時調用
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
// 當新的頁面被選中時調用
@Override
public void onPageSelected(int arg0) {
// 設置底部小點選中狀態
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) {
}
// 獲得當前界面數
@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) {
// 設置已經引導
setGuided();
goHome();
}
});
}
return views.get(arg1);
}
private void goHome() {
// 跳轉
Intent intent = new Intent(activity, MainActivity.class);
activity.startActivity(intent);
activity.finish();
}
/**
*
* method desc:設置已經引導過了,下次啟動不用再次引導
*/
private void setGuided() {
SharedPreferences preferences = activity.getSharedPreferences(
SHAREDPREFERENCES_NAME, Context.MODE_PRIVATE);
Editor editor = preferences.edit();
// 存入數據
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隨便了。
效果就是如下圖片
所以總結一下,我們可以使用ViewPager做什么:
1.程序使用導航,外加底部圓點的效果,這個在微信示例里介紹了
2.頁卡滑動,加上菜單的效果,不管是之前的支持手勢也支持底部圖標點擊的微信,還是今天的微博。
相互學習,共同努力!
微信號:romance-l