天天看點

ViewPager的過渡動畫

開篇

作為我的第一篇部落格,可能寫的時候還有些粗糙,知識點的叙述也不夠明确,不過這才是開始,而且每一篇部落格都會用心去編寫,所寫的内容都是自己在學習安卓中的一些發現和見解,基于我的技術水準有限,如有不足的可以留言,有錯誤的地方也請及時批評指出。

沒有前戲,直接上重點

因為是自己的第一篇,也是我第一次寫部落格,對于各種排版的問題,大家可以忽略,重點是代碼和一些重要的說明我都會用粗體标出的。
  1. 關于ViewPager 的基本使用和擴充卡的建立,這些内容在本文中都沒有,在網上有很多資料的,本文重點是在過渡動畫

  2. 或者說這篇文章主要是研究ViewPager的一個方法setPageTransformer(),這是在API11,也就是android3.0之後安卓官方給我們提供的一個能夠改變ViwePager過渡動畫的一個方法,或者說接口。

  3. 先看一下源碼,本人英語水準有限,大家自行了解閱讀吧,怕誤導各位了。
    /**
         * Set a {@link PageTransformer} that will be called for each attached page whenever
         * the scroll position is changed. This allows the application to apply custom property
         * transformations to each page, overriding the default sliding look and feel.
         *
         * <p><em>Note:</em> Prior to Android 3.0 the property animation APIs did not exist.
         * As a result, setting a PageTransformer prior to Android 3.0 (API 11) will have no effect.</p>
         *
         * @param reverseDrawingOrder true if the supplied PageTransformer requires page views
         *                            to be drawn from last to first instead of first to last.
         * @param transformer PageTransformer that will modify each page's animation properties
         */
        public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
            if (Build.VERSION.SDK_INT >= 11) {
                final boolean hasTransformer = transformer != null;
                final boolean needsPopulate = hasTransformer != (mPageTransformer != null);
                mPageTransformer = transformer;
                setChildrenDrawingOrderEnabledCompat(hasTransformer);
                if (hasTransformer) {
                    mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD;
                } else {
                    mDrawingOrder = DRAW_ORDER_DEFAULT;
                }
                if (needsPopulate) populate();
            } 
               

  4. android官方文檔上也對于這個方法的使用,感興趣的可以參考一下。(我記得有,不過剛才找了沒找到,丢人啊!)

精華部分

這是我自己經過多次試驗之後得到的代碼與結論,可以直接看代碼,代碼中的注釋也許會讓你對這個方法産生一種感覺,原來改變動畫這麼簡單

vp.setPageTransformer(true, new PageTransformer() {
			@Override
			public void transformPage(View view, float position) {
				float mdistance=0.5f;
				if(position<-1){
					//設定成不可見就可以
					view.setAlpha(0);
				}else if(position<=0){
					//小于零的position所對應的是在螢幕左邊的view
					//劃入螢幕時position是從-1到0
					//劃出螢幕時position是從0到-1
					//執行縮放時,不設定中心點會自動選擇view中心
					view.setAlpha(1+position);
					view.setScaleY((position+1)/2+mdistance);

				}else if(position<=1){
					//大于零的position所對應的是在螢幕右邊的view
					//劃入螢幕的時候position是從1到0
					//劃出螢幕的時候position是從0到1
					//執行縮放時,不設定中心點會自動選擇view的中心
					view.setAlpha(1-position);
					view.setScaleY((1-position)/2+mdistance);
				}else {
					//設定成不可見就可以
					view.setAlpha(0);    
				}
			}
		});
           

現在給大家稍微解釋一下,ViewPager在調用setPageTransformer()方法後會要求重寫一個方法就是transformPage(),其實就是重寫ViewPager的一個内部接口裡的方法,重要的是方法的參數,第一個是view,可以不管他,重點是第二個position,網上很多資料,官方也給了一下說明,大概的意思就是當處于螢幕正中的時候position是0,當左邊的view恰好劃出螢幕時是-1,右邊的view恰好劃入的時候是1。當我讀這種解釋的時候,完全不了解是什麼意思,還有說左右兩邊各占螢幕一半的時候,左邊的是-0.5,右邊的是+0.5,不懂之後我就進行了一系列的試驗,最終得出了代碼中注釋部分的結論。

  1. 首先position小于0就是指螢幕左邊的view的位置,position大于0就是指螢幕右邊的view的位置,小于-1和大于1均可以不用考慮,因為看不見的。

  2. 對于position小于0來說,也就是相對于螢幕左邊的view來說有兩種情況,一種就是劃入螢幕,此時position的變化是從-1到0的,另一種就是劃出螢幕,此時position的變化是從0到-1的。這都是指螢幕左邊的view。

  3. 對于position大于0來說,也就是相對于螢幕右邊的view來說也有兩種情況,一種劃入時,position變化是從1到0,另一種就是劃出時,position變化是從0到1。這裡指的是螢幕右邊的view。

  4. 當我們了解了position的基本變化了之後就是一嘗試實作自己想要的動畫效果了,對于小于-1和大于1的情況可以直接設定透明度為0就可以了,官方也是這麼寫的。當處于-1到0,和0到1之間時,這個時候可以調用view的各種set方法來實作你想要的動畫效果,透明度啊,縮放啊,平移啊,旋轉啊,都可以,重點的是對于position(位置)的了解。

  5. 對于相對于在螢幕左邊的view來說,我們隻需要設定劃出或者劃入時的一種動畫方案即可,因為兩種情況下position的變化是相對的,但是如果你想得到更複雜的動畫效果,比如劃入的時候采用縮放的方式進入,劃出的時候采用旋轉的方式劃出,這也是可以的,這需要你對position的變化進行判斷,來決定采用什麼樣的過場動畫,通常情況下,我們隻需要寫一種就可以了。

  6. 對于動畫的實作方案,這就可以根據個人喜好取設定了,剩下的都是邏輯問題,大家可以自行去嘗試實作一下,其實也挺好玩的,附上代碼中所實作的效果,真的挺簡單的。(這個怎麼插入動畫效果啊?)好吧,等我之後的文章在上圖吧,現在有點研究不明白這個部落格怎麼上效果圖了,那這篇文章到這就結束了。

總結一下吧!

先說一下在我最近使用中遇到的問題,昨天在使用viewpager+fragment的時候遇到了,發現在更改了過渡動畫了之後在左右滑動的時候,如果不滑動到螢幕的邊界的話,fragment所對應的視圖不會充滿螢幕的,會保持在手指離開螢幕時view的狀态,但在功能上沒有問題,不知道是哪裡出了毛病。

作為我的第一文章,寫得有點亂,也沒有什麼内容,至少對于一個方法中一個參數的變化過程的分析,不過這确實是我經過獨立的實踐之後發現的結論(油然而生的成就感),希望能夠對看這文章的能有所幫助,同時也歡迎批評指正,多多交流。