給ViewPager添加一個(gè)自定義的滾動(dòng)監(jiān)聽器

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)用:


onPageScrolled0-1.png

從第1頁滑動(dòng)到第2頁onPageScrolled調(diào)用:


onPageScrolled1-2.png

從第2頁滑動(dòng)回到第1頁onPageScrolled調(diào)用:
onPageScrolled2-1.png

從第1頁滑動(dòng)回到第0頁onPageScrolled調(diào)用:


onPageScrolled1-0.png

通常情況下,這個(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)用:


onPageScrolled0-1.png

從第1頁滑動(dòng)到第2頁onPageScroll調(diào)用:


onPageScrolled1-2.png

從第2頁滑動(dòng)到第1頁onPageScroll調(diào)用:
onPageScrolled2-1.png

從第1頁滑動(dòng)到第0頁onPageScroll調(diào)用:
onPageScrolled1-0.png

通過封裝過后的OnPageScrollListener怕篷,可以很方便的定義各種樣式的ViewPager指示器。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酗昼,一起剝皮案震驚了整個(gè)濱河市廊谓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌麻削,老刑警劉巖蒸痹,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異呛哟,居然都是意外死亡电抚,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門竖共,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝙叛,“玉大人,你說我怎么就攤上這事公给〗枇保” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵淌铐,是天一觀的道長肺然。 經(jīng)常有香客問我,道長腿准,這世上最難降的妖魔是什么际起? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮吐葱,結(jié)果婚禮上街望,老公的妹妹穿的比我還像新娘。我一直安慰自己弟跑,他們只是感情好灾前,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孟辑,像睡著了一般哎甲。 火紅的嫁衣襯著肌膚如雪蔫敲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天炭玫,我揣著相機(jī)與錄音奈嘿,去河邊找鬼。 笑死吞加,一個(gè)胖子當(dāng)著我的面吹牛裙犹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播榴鼎,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼伯诬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了巫财?” 一聲冷哼從身側(cè)響起盗似,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎平项,沒想到半個(gè)月后赫舒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闽瓢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年接癌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扣讼。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缺猛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出椭符,到底是詐尸還是另有隱情荔燎,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布销钝,位于F島的核電站有咨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蒸健。R本人自食惡果不足惜座享,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望似忧。 院中可真熱鬧渣叛,春花似錦、人聲如沸橡娄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挽唉。三九已至滤祖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓶籽,已是汗流浹背匠童。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留塑顺,地道東北人汤求。 一個(gè)月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像严拒,于是被迫代替她去往敵國和親扬绪。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容