叨叨ViewPager那些事兒(二)

前言

上一篇叨叨ViewPager那些事兒(一)說了一點(diǎn)ViewPager概況,這篇打算說說實(shí)際應(yīng)用。


從動畫效果說起

先祭上一份谷歌官方的Transformer示例
效果如下


代碼實(shí)現(xiàn)是這樣

public class DepthPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.75f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        } else if (position <= 0) { // [-1,0]
            // Use the default slide transition when moving to the left page
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);

        } else if (position <= 1) { // (0,1]
            // Fade the page out.
            view.setAlpha(1 - position);

            // Counteract the default slide transition
            view.setTranslationX(pageWidth * -position);

            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

乍一看有點(diǎn)懵懂,一步一問 慢慢來

?transformPage(View view, float position)兩個參數(shù)是何含義


第一個參數(shù)為各頁卡對象,第二個是各個頁卡對于當(dāng)前所展示頁卡的相對位置,例如,當(dāng)前頁卡的position為0,下一張位置為1,前一張則為-1。而ViewPager滑動中,position的值是處于平滑變化中的,這就為我們處理動畫提供了機(jī)會。

為何position < -1position > 1時設(shè)置可見度為0
如前問分析,position < -1position > 1指代頁卡所處區(qū)間為[-Infinity,-1)和(1,+Infinity],在可見范圍之外,從節(jié)省繪制資源的角度出發(fā),自然可見度為0。

?position (0,1]區(qū)間時為何要設(shè)置偏移度為(pageWidth * -position)
官方注釋Counteract the default slide transition,抵消頁面滑動時的默認(rèn)偏移量。如頁面處在中間時偏移量為0*width,移至右邊為1*width,從中間往右移除時position0-->1漸變,默認(rèn)偏移量為position*width

滑動動畫的縮放效果如何計算
如效果圖示,當(dāng)下一張頁卡相對位置從1-->0變化時,scale的變化方向?yàn)?code>MIN_SCALE(m)-->1,不妨列個公式
(1-position)/(position-0)=(m-scale)/(scale-1)s=(1-position)/(1-position*m)(對。。跟示例代碼不一樣。。但是效果一樣哦。。
也可以理解為1-scale=|(m-1)|/(1-0)*position,scale從1-->m,位置從0-->1,即每單位position的變化量為|(m-1)|/(1-0),乘上position得出變化量。

理論儲備到位之后,自力更生的第一步就是,實(shí)踐!
下邊我們來寫一個左右位移,同時展示三張卡片的動畫,預(yù)想中效果大概是這樣


根據(jù)設(shè)想計算,左右兩邊的頁卡大小應(yīng)為中間大頁卡的0.9倍,左右頁卡的偏移量約為±0.2倍頁卡寬。
故設(shè)定MIN_Trans_INDEX = 0.2f,MIN_SCALE_INDEX = 0.9f。如上分析,我們只關(guān)心[-1,1]區(qū)間頁卡的動畫,
每單位position的scale變化量絕對值為(1-MIN_SCALE_INDEX)/(1-0),即1-scale=|position|*(1-MIN_SCALE_INDEX)/(1-0)scale=1-|position|*(1-MIN_SCALE_INDEX)
同理,每單位position的translationx變化量為pageWidth*(1-MIN_Trans_INDEX)/(1-0),即|0-translationx|=|position|*pageWidth*(1-MIN_Trans_INDEX)|translationx|=|position|*pageWidth*(1-MIN_Trans_INDEX),然而viewpager頁卡滑動過程中的默認(rèn)偏移量絕對值為pageWidth * position,故需在上式基礎(chǔ)上減pageWidth * position,|translationx|=|position|*pageWidth*MIN_Trans_INDEX
計算完畢,寫入代碼后發(fā)現(xiàn),效果是出來了,但是反應(yīng)好像永遠(yuǎn)。慢半拍。當(dāng)前頁滑動到位后,下一頁才出現(xiàn),體驗(yàn)不太美妙,如下動圖所示

查看代碼后思考,應(yīng)該是[-1,1]位置限定導(dǎo)致,左右兩頁分別滑動到-1和1時才開始做動畫,而此時這兩張頁卡已經(jīng)出現(xiàn)在屏幕上,所以看起來就像“慢了半拍”。
嘗試增加一點(diǎn)“緩沖量”,改動如下

public class MyTransPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_Trans_INDEX = 0.2f;
    private static final float MIN_SCALE_INDEX = 0.9f;

    @Override
    public void transformPage(@NonNull View page, float position) {
        int pageWidth = page.getWidth();
        if (position < -1.1) { // [-Infinity,-1.1)
            // This page is way off-screen to the left.
            page.setAlpha(0);
        } else if (position <= 0) { // [-1.1,0]
            // Use the default slide transition when moving to the left page
            page.setAlpha(1);
            page.setTranslationX(-pageWidth * position * MIN_Trans_INDEX);
            page.setScaleX((1 - MIN_SCALE_INDEX) * position + 1);
            page.setScaleY((1 - MIN_SCALE_INDEX) * position + 1);
            Log.i("test", page.getTag()+"--"+((1 - MIN_SCALE_INDEX) * position + 1));
        } else if (position <= 1.1) { // (0,1.1]
            // Fade the page out.
            page.setAlpha(1);
            // Counteract the default slide transition
            page.setTranslationX(-pageWidth * position * MIN_Trans_INDEX);
            page.setScaleX(1 - (1 - MIN_SCALE_INDEX) * position);
            page.setScaleY(1 - (1 - MIN_SCALE_INDEX) * position);
        } else { // (1.1,+Infinity]
            // This page is way off-screen to the right.
            page.setAlpha(0);
        }
    }
}

再次運(yùn)行。這才是想要的效果嘛


問題來了

之前遇到過一個現(xiàn)象,刷新ViewPager,調(diào)用notifyDataSetChanged(),如下。

誒,怎么肥事!左右兩邊的頁卡去哪了!冷靜一下,刷新時對當(dāng)前頁卡重繪,若不需滾動,則pageoffset始終為0,transformer的動畫效果無法顯示??磥硪肫椒€(wěn)刷新,還需手動更新單條數(shù)據(jù)。
行動起來,更改如下邏輯

@Override
    public void onClick(View v) {
        if (v.getId() == R.id.tv_notify) {
            if (mCurPageIndex == 3) {//測試,代表邏輯需跳轉(zhuǎn)到的頁卡
                isNeedNotify = true;
            }
            //更新當(dāng)前頁卡數(shù)據(jù)
            updateViewPager(mCurPageIndex);
        }
    }
private void updateViewPager(int position) {
        if (isNeedNotify) {//需要滾動時,調(diào)用notifyDataSetChanged重走instantiateItem和destroyItem邏輯
            mPagerAdapter.notifyDataSetChanged();
            mViewPager.setCurrentItem(3);
            isNeedNotify = false;
        }
        //僅需更新當(dāng)前頁時則單獨(dú)刷新當(dāng)前頁卡view
        MyViewPagerItem item = mPageItemList.get(position);
        if (item != null) {
            PageItemBean bean = new PageItemBean();
            bean.num = position;
            bean.tip = mContext.getString(R.string.num_tip, position + 1 + "");
            item.updateUI(bean);
        }
    }

重跑程序,問題解決,Demo先放下。
為解決問題臨時想的方案,是實(shí)現(xiàn)更新的一條思路但感覺不夠優(yōu),歡迎各路大神指點(diǎn)。


最后

本想多寫一點(diǎn),但動畫已經(jīng)占了不少篇幅,先在這結(jié)束吧。這個系列會努力補(bǔ)充,歡迎多多指點(diǎn)和關(guān)注。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,100評論 25 708
  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明AGI閱讀 16,003評論 3 119
  • 原文鏈接:https://github.com/opendigg/awesome-github-android-u...
    IM魂影閱讀 32,954評論 6 472
  • 人破除自我限制、逐漸改變的過程好比毛毛蟲,雖然過程痛苦然而前景優(yōu)美。 文/ 七彩霞衣 這幾天讀朱光潛先生的《談讀書...
    七彩霞衣閱讀 417評論 1 3
  • 家人們好: 這周有件事情極為震撼了我,讓我覺得這世界上所有的生命都值得尊重,任何生命體都賦予極高的...
    書_贏閱讀 159評論 0 1