ViewPager是在日常開發(fā)業(yè)務(wù)中使用較多的入撒,通常我們都會使用OnPagerChangeListener來監(jiān)聽ViewPager頁面的滾動(dòng)和狀態(tài)變化:
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 頁面正在滾動(dòng)時(shí)不斷調(diào)用
Log.d("ViewPager", "onPageScrolled————>"
+ " position:" + position
+ " positionOffest:" + positionOffset
+ " positionOffsetPixels:" + positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
// 頁面選中時(shí)調(diào)用
Log.d("ViewPager", "onPagerSelected————> position:" +position);
}
@Override
public void onPageScrollStateChanged(int state) {
// 頁面的滾動(dòng)狀態(tài)變化時(shí)調(diào)用
Log.d("ViewPager", "onPageScrollStateChanged————> state:" + state);
}
});
在onPageScrolled方法中:
position:在滑動(dòng)過程中蘸嘶,有可能是你當(dāng)前頁面位置,也有可能是你要滑動(dòng)到的下一個(gè)頁面位置;
positionOffset:頁面位置的偏移量储藐,值為0到1之間。頁面從右向左滑出時(shí)级历,值從0逐漸變?yōu)?并且在趨近1的時(shí)候突變?yōu)?互婿。頁面從左向右滑出時(shí)捣郊,值從1逐漸變?yōu)?;
positionOffsetPixels:頁面滑動(dòng)的像素值慈参,從右向左滑動(dòng)時(shí)呛牲,該值逐漸變大,從左向右滑動(dòng)時(shí)懂牧,逐漸變小侈净。
從第0頁滑動(dòng)到第1頁onPageScrolled調(diào)用:
從第1頁滑動(dòng)到第2頁onPageScrolled調(diào)用:
從第2頁滑動(dòng)回到第1頁onPageScrolled調(diào)用:
從第1頁滑動(dòng)回到第0頁onPageScrolled調(diào)用:
通常情況下,這個(gè)監(jiān)聽器中的三個(gè)回調(diào)方法已經(jīng)完全能夠滿足我們的業(yè)務(wù)需要僧凤。
但是因?yàn)榈谝粋€(gè)參數(shù)position在滑動(dòng)過程中不是很明確的表示是當(dāng)前頁面位置還是下一個(gè)頁面的位置,我們還需要通過positionOffset或者positionOffsetPixels來判斷元扔。
因此我們通過OnPageChangedListener來封裝一個(gè)自定義的滾動(dòng)監(jiān)聽器躯保,使用這個(gè)自定義的滾動(dòng)監(jiān)聽器,在頁面滑動(dòng)時(shí)澎语,可以很明確的回調(diào)進(jìn)入的頁面途事,離開的頁面验懊,以及滑動(dòng)百分比、狀態(tài)和最后選中的頁面尸变。
1.定義滾動(dòng)監(jiān)聽接口
/**
* ViewPage的頁面滾動(dòng)監(jiān)聽器
*/
public interface OnPageScrollListener {
/**
* 頁面滾動(dòng)時(shí)調(diào)用
*
* @param enterPosition 進(jìn)入頁面的位置
* @param leavePosition 離開的頁面的位置
* @param percent 滑動(dòng)百分比
*/
void onPageScroll(int enterPosition, int leavePosition, float percent);
/**
* 頁面選中時(shí)調(diào)用
*
* @param position 選中頁面的位置
*/
void onPageSelected(int position);
/**
* 頁面滾動(dòng)狀態(tài)變化時(shí)調(diào)用
*
* @param state 頁面的滾動(dòng)狀態(tài)
*/
void onPageScrollStateChanged(int state);
}
2.在ViewPagerHelper中來實(shí)現(xiàn)滑動(dòng)時(shí)頁面位置义图、百分比的回調(diào)
/**
* ViewPager輔助類
*/
public class ViewPagerHelper {
private double mLastPositionOffsetSum; // 上一次滑動(dòng)總的偏移量
private OnPageScrollListener mOnPageScrollListener;
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 當(dāng)前總的偏移量
float currentPositionOffsetSum = position + positionOffset;
// 上次滑動(dòng)的總偏移量大于此次滑動(dòng)的總偏移量,頁面從右向左進(jìn)入(手指從右向左滑動(dòng))
boolean rightToLeft = mLastPositionOffsetSum <= currentPositionOffsetSum;
if (currentPositionOffsetSum == mLastPositionOffsetSum) return;
int enterPosition;
int leavePosition;
float percent;
if (rightToLeft) { // 從右向左滑
enterPosition = (positionOffset == 0.0f) ? position : position + 1;
leavePosition = enterPosition - 1;
percent = (positionOffset == 0.0f) ? 1.0f : positionOffset;
} else { // 從左向右滑
enterPosition = position;
leavePosition = position + 1;
percent = 1 - positionOffset;
}
if (mOnPageScrollListener != null) {
mOnPageScrollListener.onPageScroll(enterPosition, leavePosition, percent);
}
mLastPositionOffsetSum = currentPositionOffsetSum;
}
public void onPageSelected(int position) {
if (mOnPageScrollListener != null) {
mOnPageScrollListener.onPageSelected(position);
}
}
/**
* @param state 當(dāng)前滑動(dòng)狀態(tài)
* ViewPager.SCROLL_STATE_IDLE 頁面處于閑置召烂、穩(wěn)定狀態(tài)碱工,即沒被拖動(dòng)也沒慣性滑動(dòng)
* ViewPager.SCROLL_STATE_DRAGGING 頁面正在被用戶拖動(dòng),即手指正在拖動(dòng)狀態(tài)
* Viewpager.SCROLL_STATE_SETTLING 頁面處于即將到達(dá)最終狀態(tài)的過程奏夫,即手指松開后慣性滑動(dòng)狀態(tài)
*/
public void onPageScrollStateChanged(int state) {
if (mOnPageScrollListener != null) {
mOnPageScrollListener.onPageScrollStateChanged(state);
}
}
public void setOnPageScrollListener(OnPageScrollListener onPageScrollListener) {
mOnPageScrollListener = onPageScrollListener;
}
}
3.采用工具類ViewPagerUtil來綁定ViewPager和OnPageScrollListener
/**
* ViewPager工具類
*/
public class ViewPagerUtil {
/**
* 給ViewPager綁定自定義的滾動(dòng)監(jiān)聽
*
* @param viewPager
* @param onPageScrollListener
*/
public static void bind(@NonNull ViewPager viewPager, @NonNull OnPageScrollListener onPageScrollListener) {
final ViewPagerHelper helper = new ViewPagerHelper();
// 給helper設(shè)置滾動(dòng)監(jiān)聽
helper.setOnPageScrollListener(onPageScrollListener);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
helper.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
helper.onPageSelected(position);
}
@Override
public void onPageScrollStateChanged(int state) {
helper.onPageScrollStateChanged(state);
}
});
}
}
4.調(diào)用工具類方法實(shí)現(xiàn)綁定
ViewPagerUtil.bind(mViewPager, new OnPageScrollListener() {
@Override
public void onPageScroll(int enterPosition, int leavePosition, float percent) {
Log.d("ViewPager", "onPageScrolled————>"
+ " 進(jìn)入頁面:" + enterPosition
+ " 離開頁面:" + leavePosition
+ " 滑動(dòng)百分比:" + percent);
}
@Override
public void onPageSelected(int position) {
Log.d("ViewPager", "onPageSelected————> position:" + position);
}
@Override
public void onPageScrollStateChanged(int state) {
Log.d("ViewPager", "onPageScrollStateChanged————> state:" + state);
}
});
運(yùn)行結(jié)果:
從第0頁滑動(dòng)到第1頁onPageScroll調(diào)用:
從第1頁滑動(dòng)到第2頁onPageScroll調(diào)用:
從第2頁滑動(dòng)到第1頁onPageScroll調(diào)用:
從第1頁滑動(dòng)到第0頁onPageScroll調(diào)用:
通過封裝過后的OnPageScrollListener怕篷,可以很方便的定義各種樣式的ViewPager指示器。