天天看點

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

GitHub:lightSky

微網誌:    light_sky , 即時分享最新技術,歡迎關注

前言

前兩天看到鮑永章分享的Great animations with PageTransformer以及農民伯伯分享的Create ViewPager transitions 文章,都是通過ViewPager來實作酷炫的動畫,而現在的App中ViewPager的動畫使用也非常的廣泛。正好最近一直研究動畫,那麼就趁熱打鐵,分析一下相關的開源庫吧。本篇文章介紹的ViewPager動畫,可以分為兩類,第一類是針對于ViewPager的界面滑動動畫(這個是PageTransformer的真正用途),分析并比較了AndroidImageSlider和JazzyViewPager兩種實作,第二類是對ViewPager中的内容進行動畫處理,這個是這個是PageTransformer的巧妙應用,處理好了可以達到很棒的互動效果,示例是Yahoo天氣的視差效果。

ViewPager動畫的實作原理

從3.0開始,ViewPager開始支援自定義切換動畫,暴露的接口為PageTransformer,是以隻要實作PageTransformer接口和其唯一的方法transformPage(View view, float position)即可。

/**
   * A PageTransformer is invoked whenever a visible/attached page is scrolled.
   * This offers an opportunity for the application to apply a custom transformation
   * to the page views using animation properties.
   *
   * <p>As property animation is only supported as of Android 3.0 and forward,
   * setting a PageTransformer on a ViewPager on earlier platform versions will
   * be ignored.</p>
   */
  public interface PageTransformer {
      /**
       * Apply a property transformation to the given page.
       *
       * @param page Apply the transformation to this page
       * @param position Position of page relative to the current front-and-center
       *                 position of the pager. 0 is front and center. 1 is one full
       *                 page position to the right, and -1 is one page position to the left.
       */
      public void transformPage(View page, float position);
 }
           
  • 參數position

    給定界面的位置相對于螢幕中心的偏移量。在使用者滑動界面的時候,是動态變化的。那麼我們可以将position的值應用于setAlpha(), setTranslationX(), or setScaleY()方法,進而實作自定義的動畫效果。

    另外在ViewPager滑動時,記憶體中存活的Page都會執行transformPage方法,在滑動過程中涉及到兩個Page,目前頁和下一頁,而它們的position值是相反的(因為是相對運動,一個滑入一個滑出),比如,頁面A向右滑動到螢幕一半,頁面B也正好處于一半的位置,那麼A和B的position為:0.5 和 -0.5

    position == 0 :目前界面位于螢幕中心的時候

    position == 1 :目前Page剛好滑出螢幕右側

    position == -1 :目前Page剛好滑出螢幕左側

AndroidImageSlider動畫庫解析

要說到動畫庫,肯定會想到代碼家,沒錯,代碼家也開源了一個ViewPager效果的庫:AndroidImageSlider ,我們就來分析下這個庫的實作。AndroidImageSlider除了基本的page動畫外,也支援使用者為Page内容添加自定義的動畫,比如下面描述框的動畫。

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

AndroidImageSlider相容性的實作原理

因為API 11才開始支援PagerTransformer. 這裡面修改了Android系統的ViewPager,名為ViewPagerEx,ViewPager裡面有一段if邏輯判斷是否在3.0以上使用PagerTransformer。因為PagerTransformer動畫效果的實作依賴了PropertyViewAnim。但代碼家的這個庫使用NineOldAndroids實作了向3.0之前的相容。是以就把這個if條件去掉了,其它部分都沒變。

/**
 * @author daimajia : I just remove the if condition in setPageTransformer() to make it compatiable with Android 2.0+
 * of course, with the help of the NineOldDroid.
 * Thanks to JakeWharton.
 * http://github.com/JakeWharton/NineOldAndroids
 */
           

AndroidImageSlider的總體設計

  • BaseTransformer

    所有Transformer的基類,實作了ViewPagerEx.PageTransformer接口以及transformPage方法,并提供了onPreTransform(View view, float position)、onPostTransform(View view, float position)、onTransform(View view, float position);

    分别在transformPage前後調用,用來處理為每一次的執行動畫前的準備和結束動作,比如還原所有的動畫狀态。

  • BaseAnimationInterface:

    ViewPagerEx執行Transformer動畫的時候注入一些自己的動畫。你需要實作該接口,然後實作以下4個方法,擷取SlideView中的View,實作自己的動畫。比如底部的DescriptionText動畫DescriptionAnimation 出現時的動畫就是onNextItemAppear中添加的,你可以點入,看下源碼

    onPrepareCurrentItemLeaveScreen(View current)

    onPrepareNextItemShowInScreen(View next)

    onCurrentItemDisappear(View view)

    onNextItemAppear(View view)

而這4個方法的調用是在BaseTransformer中。BaseTransformer統一管理了Page滑動時的所有動畫。為了擷取這4個方法的調用時機,也是煞費苦心啊,先說下思路:

因為ViewPager滑動的時候transformPage方法是實時調用的,這裡擷取最初兩次調用時傳入的position進行比較。通過一個HashMap<view, arraylist>來維護不同pageView的多個position。但這裡為了優化,隻取前兩個position做比較。

先判斷起始滑動的方向,然後再判斷下一次滑動的方向,兩次結果作差來判斷到底哪個page要離開界面還是進入界面。

确定2個界面的4種臨界狀态

if(mCustomAnimationInterface != null){
            if(h.containsKey(view) == false || h.get(view).size() == 1){
                if(position > -1 && position < 1){
                    if(h.get(view) == null){
                        h.put(view,new ArrayList<Float>());//為每個View建立一個List,來存儲偏移分數position
                    }
                    h.get(view).add(position);//向指定的View中添加偏移分數
                    if(h.get(view).size() == 2){
                        float zero = h.get(view).get(0);
                        float cha = h.get(view).get(1) - h.get(view).get(0);//目前滑動的位移偏移量分數差: newfraction - oldfraction
                        if(zero > 0){//起始時,向左滑動,目前Page中心位于螢幕中心左側
                            //判斷滑動趨勢,如果繼續向左側滑動,position從0到1越來越大 newfraction > oldfraction
                            if(cha > -1 && cha < 0){//向右側滑動
                                //in
                                mCustomAnimationInterface.onPrepareNextItemShowInScreen(view);//下一個Page将要進入螢幕
                            }else{//cha > 0 繼續向左側滑動
                                //out
                                mCustomAnimationInterface.onPrepareCurrentItemLeaveScreen(view);//目前Page将要離開螢幕
                            }
                        }else{//起始時,向右滑動,目前Page中心位于螢幕中心右側
                            //判斷滑動趨勢,如果繼續向右側滑動,position從0到-1越來越小 newfraction < oldfraction
                            if(cha > -1 && cha < 0){//負值,繼續向右滑動,是以目前page将要滑出螢幕
                                //out
                                mCustomAnimationInterface.onPrepareCurrentItemLeaveScreen(view);//目前Page将要離開螢幕
                            }else{//向左滑動
                                //in
                                mCustomAnimationInterface.onPrepareNextItemShowInScreen(view);//下一個Page将要離開螢幕
                            }
                        }
                    }
                }
            }
        }
 boolean isApp,isDis;
    /**
     * Called each {@link #transformPage(View, float)} call after {@link #onTransform(View, float)} is finished.
     *
     * @param view
     * @param position
     */
    protected void onPostTransform(View view, float position) {
        if(mCustomAnimationInterface != null){
            if(position == -1 || position == 1){//目前界面剛好完全移除界面
                mCustomAnimationInterface.onCurrentItemDisappear(view);
                isApp = true;
            }else if(position == 0){
                mCustomAnimationInterface.onNextItemAppear(view);//下一個Page剛好完全顯示
                isDis = true;
            }
            if(isApp && isDis){
                h.clear();
                isApp = false;
                isDis = false;
            }
        }
    }
           
  • BaseSliderView:

    該類就是SlideView的基類,持有SlideView的一些公共方法,比如設定SliderView的image資源的方法image(File file),圖檔加載異常和失敗的處理,empty(URL)用于展示,errorDisappear(boolean disappear)。這種思想和一個EmptyView有些類似,在我公司的項目也是使用了這種方式,比如通常一個ListView的界面,會有一個包裝後的progressbar(包含各種情況的處理)來顯示進度,當加載失敗的時候,或者無資料的時候,可以調用該progressbar身上的方法,去決定顯示何種布局。使用起來很友善。當然如果你的SliderView更複雜,你可以通過實作BaseSliderView,然後實作自己的SliderView。

下面兩個類就是切換的View:

DefaultSliderView:實作了BaseSliderView,該View預設就是一張圖檔

TextSliderView:帶有圖檔和描述性文字的View

  • Sliderlayout:

    一個控制中心,将InfiniteViewPager,PageIndicator,粘合在一起,控制動畫的樣式,ViewPager輪循的播放。

addSlider:向ViewPager中添加一個SlideView

startAutoCycle:啟動輪播

pauseAutoCycle:停止輪播

setDuration: 輪播間隔

setPagerTransformer 為ViewPager設定自定義的PageTransformer

onInterceptTouchEvent 在使用者手勢按下的時候,就停止輪循

Note:

這裡在onInterceptTouchEvent中處理而不能再onTouchEvent中處理。因為SlideView會消費掉點選事件,事件被消費了,沒法傳回給SlideLayout的onTouchEvent中。

OK,總體設計弄清楚後,剩下來就是動畫中最核心的部分了,就是動畫效果的實作,這裡隻簡單的介紹Accordion動畫的實作,其它的大家可以自己分析。關于PropertyView動畫的使用,可以參考我的另一篇文章:PropertyAnim實際應用

Accordion

public class AccordionTransformer extends BaseTransformer {
    @Override
    protected void onTransform(View view, float position) {
        ViewHelper.setPivotX(view,position < 0 ? 0 : view.getWidth());
        ViewHelper.setScaleX(view,position < 0 ? 1f + position : 1f - position);
    }
}
           

代碼家在README中注明了Thanks JazzyViewPager,開始沒注意,後來看JazzyViewPager的源碼時候偶然發現AndroidImageSlider的一些實作的靈感是來自JazzyViewPager項目。不過JazzyViewPager的實作方式略顯複雜,沒有使用PageTransformer接口,而是使用了OnPageChangeListener接口的onPageScrolled方法。

下面簡單的看下JazzyViewPager庫的動畫實作,它将positionOffset作為參數控制。由于positionOffset的值為[0,1),是以就需要分别處理正負的情況。另外JazzyViewPager是通過維護一個LinkedHashMap來持有Page的引用。在Adapter添加界面的時候,會調用JazzyViewPager的 setObjectForPosition(Object obj, int position) 方法存入到集合中去。然後在onPageScrolled方法中再根據position擷取目前Page的前一個mLeft和後一個mRight界面,分别對前後兩個界面添加動畫。

兩種方式的關鍵參數差別

onPageScrolled(int position, float positionOffset, int positionOffsetPixels)方法的參數:

/**
         * This method will be invoked when the current page is scrolled, either as part
         * of a programmatically initiated smooth scroll or a user initiated touch scroll.
         *
         * @param position Position index of the first page currently being displayed.
         *                 Page position+1 will be visible if positionOffset is nonzero.
         * @param positionOffset Value from [0, 1) indicating the offset from the page at position.
         * @param positionOffsetPixels Value in pixels indicating the offset from position.
         */
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
           

下面是列印的PageTransformer接口的transformPage時position的值:相鄰兩界面的絕對值的和為1.而正負則表示了滑入和滑出狀态

12-15 21:03:13.025    I/System.out﹕ transformPage----------------------    -0.43611112
       12-15 21:03:13.025    I/System.out﹕ transformPage----------------------    0.5638889
       
12-15 21:03:13.045    I/System.out﹕ transformPage----------------------    -0.38055557
       12-15 21:03:13.045    I/System.out﹕ transformPage----------------------    0.61944443
       
12-15 21:03:13.045    I/System.out﹕ transformPage----------------------    -0.37777779
       12-15 21:03:13.045    I/System.out﹕ transformPage----------------------    0.62222224
       
12-15 21:03:13.055    I/System.out﹕ transformPage----------------------    -0.32916668
       12-15 21:03:13.055    I/System.out﹕ transformPage----------------------    0.67083335
       
12-15 21:03:13.065    I/System.out﹕ transformPage----------------------    -0.32222223
       12-15 21:03:13.065    I/System.out﹕ transformPage----------------------    0.67777777
       
12-15 21:03:13.075    I/System.out﹕ transformPage----------------------    -0.27916667
       12-15 21:03:13.075    I/System.out﹕ transformPage----------------------    0.72083336
           

onPageScrolled方法的positionOffset的值為 [0, 1) ,而PageTransformer接口的transformPage(View page, float position) 已經标好了正負值(滑入和滑出),如果你的動畫正好是相對的,那麼用transfromPage就簡單的多。

我們取同一種動畫效果Cube來比較一下JazzyViewPager和AndroidImageSlider兩者的實作:

JazzyViewPager部分源碼

@Override
	public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
		
		...
		float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;
		mLeft = findViewFromObject(position);
		mRight = findViewFromObject(position+1);
		switch (mEffect) {
			case Standard:
				break;
			...
			case animateCube:
				animateCube(mLeft, mRight, effectOffset);
				break;
		}
	}
	...
	private void animateCube(View left, View right, float positionOffset, boolean in) {
		if (mState != State.IDLE) {
			if (left != null) {
				manageLayer(left, true);
				mRot = (in ? 90.0f : -90.0f) * positionOffset;
				ViewHelper.setPivotX(left, left.getMeasuredWidth());
				ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f);
				ViewHelper.setRotationY(left, mRot);
			}
			if (right != null) {
				manageLayer(right, true);
				mRot = -(in ? 90.0f : -90.0f) * (1-positionOffset);
				ViewHelper.setPivotX(right, 0);
				ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f);
				ViewHelper.setRotationY(right, mRot);
			}
		}
	}
	public void setObjectForPosition(Object obj, int position) {//每次Adapter執行個體化View的時候,調用該方法,将執行個體化的View存入集合
			mObjs.put(Integer.valueOf(position), obj);
		}
	
	public View findViewFromObject(int position) {//根據position從集合中擷取到對應的View
			Object o = mObjs.get(Integer.valueOf(position));
			if (o == null) {
				return null;
			}
			PagerAdapter a = getAdapter();
			View v;
			for (int i = 0; i < getChildCount(); i++) {
				v = getChildAt(i);
				if (a.isViewFromObject(v, o))
					return v;
			}
			return null;
		}
	....
}
           

AndroidIamgeSlider中的CubeIn:

public class CubeInTransformer extends BaseTransformer {
	@Override
	protected void onTransform(View view, float position) {
		// Rotate the fragment on the left or right edge
        ViewHelper.setPivotX(view,position > 0 ? 0 : view.getWidth());
        ViewHelper.setPivotY(view,0);
        ViewHelper.setRotation(view,-90f * position);
	}
}
           

JazzyViewPager:CubeIn上面代碼中已經貼出:

if (left != null) {
	...
	mRot = (in ? 90.0f : -90.0f) * positionOffset;
	...
	}
if (right != null) {
	mRot = -(in ? 90.0f : -90.0f) * (1-positionOffset);
}
           

可以精簡為:

positionOffset * value
-(1-positionOffset) * value
           

與從上面的transformPage列印的position的值再比較下

12-15 21:03:13.075    I/System.out﹕ transformPage----------------------    -0.27916667
       12-15 21:03:13.075    I/System.out﹕ transformPage----------------------    0.72083336
           

結論:

發現transformPage已經幫我們處理好了一切,直接用。我們可以根據正負符号來判斷滑入和滑出的View(不用像JazzyViewPager那樣去維護一個集合了),進而針對滑入滑出做出不同或相對的的動畫。最簡單的,兩個界面如果是簡單的相對動畫(滑入對滑出),則什麼都不用處理,直接用就行了,就像下面介紹的Yahoo視差的實作一樣,具體可以看下面的講解。

大家仔細看下相同的動畫效果的處理方式,CubeInTransformer不用單獨處理上一個和下一個界面,而隻管根據position的正負判斷目前Page和下一個Page去自定義不同的動畫即可。

是以可以把AndroidImageSlider中的一些動畫效果看做是JazzyViewPager的精簡版本。

對于ViewPager如何幫我們處理View的呢?可以看下源碼:

protected void onPageScrolled(int position, float offset, int offsetPixels) {
...
if (mPageTransformer != null) {
            final int scrollX = getScrollX();
            final int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                final View child = getChildAt(i);
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (lp.isDecor) continue;
                final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
                mPageTransformer.transformPage(child, transformPos);
            }
        }
...
 }
           

小結

上面主要介紹了ViewPager的Page的滑動動畫,兩種實作方式:

PageTransformer.transformPage方式:在執行onPageScrolled方法的時候,會周遊ViewPager的所有View,并執行其transformPage方法。position是已經處理好的(方向和值)

onPageScrolled方式:略顯複雜,因為沒法拿到View,還要自己去維護一個View集合,并且positionOffset的限制,需要自己去處理不同View的position : PageA:position , PageB:-(1-position)。

為ViewPager的Page内容添加動畫,實作炫酷的互動效果

Tholotis

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

實作原理

為Page内部的View處理不同的平移速度,達到視差的效果,作者的代碼:

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 <= 1) { // [-1,1]
          
        mBlur.setTranslationX((float) (-(1 - position) * 0.5 * pageWidth));
		mBlurLabel.setTranslationX((float) (-(1 - position) * 0.5 * pageWidth));
 
		mDim.setTranslationX((float) (-(1 - position) * pageWidth));
		mDimLabel.setTranslationX((float) (-(1 - position) * pageWidth));
 
		mCheck.setTranslationX((float) (-(1 - position) * 1.5 * pageWidth));
		mDoneButton.setTranslationX((float) (-(1 - position) * 1.7 * pageWidth)); 
		// The 0.5, 1.5, 1.7 values you see here are what makes the view move in a different speed.
		// The bigger the number, the faster the view will translate.
		// The result float is preceded by a minus because the views travel in the opposite direction of the movement.
 
		mFirstColor.setTranslationX((position) * (pageWidth / 4));
 
		mSecondColor.setTranslationX((position) * (pageWidth / 1));
 
		mTint.setTranslationX((position) * (pageWidth / 2));
 
		mDesaturate.setTranslationX((position) * (pageWidth / 1));
		// This is another way to do it
		  
		  
    } else { // (1,+Infinity]
        // This page is way off-screen to the right.
        view.setAlpha(0);
    }
}
           

GitHub上類似的效果:

https://github.com/prolificinteractive/ParallaxPager

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

https://github.com/flavienlaurent/discrollview

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

這兩個項目都封裝成了庫,使用的時候也簡單,但一般我們可以通過ViewPager.PageTransformer來實作這樣的效果,從上面AndroidImageSlider與JazzyViewPager的對比中也能看到,PageTransformer的實作方式更簡單。而且ViewPager的動畫庫也很多,比如上面的JazzyViewPager。你隻需把某一個動畫效果的transformPage方法的邏輯拿來就可用,當然如果你的需求更複雜,或者ViewPager實作起來較麻煩,你可以考慮上面的兩個項目,擴充自己的思維。

JazzyViewPager:

https://github.com/jfeinstein10/JazzyViewPager/blob/master/lib/src/com/jfeinstein/jazzyviewpager/JazzyViewPager.java

https://github.com/prolificinteractive/ParallaxPager

https://github.com/flavienlaurent/discrollview

Yahoo天氣

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

原理很簡單,隻是這次處理的動畫對象是背景圖檔,減慢其平移的速度,而ViewPager的内容正常移動,進而達到視差的效果。

public class ParallaxPageTransformer implements ViewPager.PageTransformer {
	
		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(1);
 
		        } else if (position <= 1) { // [-1,1]
		            
		        	dummyImageView.setTranslationX(-position * (pageWidth / 2)); //Half the normal speed
		            
		        } else { // (1,+Infinity]
		            // This page is way off-screen to the right.
		            view.setAlpha(1);
				}
		    
 
		}
	}
           

OK,本來想自己寫,但剛巧在GitHub上發現了一個:ParallaxPagerTransformer ,并提供了APK ,實作了Yahoo天氣的效果,但多了一些縮放的效果,将縮放的代碼注釋掉就和Yahoo天氣的效果完全一樣了。另外想clone到本地的朋友注意了,由于作者的AndroidStudio版本太老,導入的時候你需要做一些處理。

作者把該Transformer抽取出來,做為了一個lib,就一個類,核心代碼很簡單,說明ViewPager.PageTransformer接口很強大啊:

@Override
  public void transformPage(View view, float position) {
      View parallaxView = view.findViewById(id);
      if (parallaxView != null) {
          if (position > -1 && position < 1) {
              float width = parallaxView.getWidth();
              parallaxView.setTranslationX(-(position * width * speed));
              float sc = ((float)view.getWidth() - border)/ view.getWidth();
              if (position == 0) {//這裡處理了縮放的效果,去掉即和Yahoo天氣的效果一樣
                  view.setScaleX(1);
                  view.setScaleY(1);
              } else {
                  view.setScaleX(sc);
                  view.setScaleY(sc);
              }
          }
      }
  }
           

看了上面的實作,大家應該知道如何去實作類似的互動動畫了,而且現在的App導航頁中,也越來越多的使用到了這樣的互動,作者在文章還列舉了News Digest的導航頁,有了思路,實作起來應該就不難了,第一、三頁的動畫上面已經介紹過,對于第二頁,其實就是一個旋轉動畫。實時的旋轉可以通過實時變化的position來處理。

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

類似的項目:

https://github.com/andraskindler/parallaxviewpager

ViewPager動畫詳解 ViewPager動畫的實作原理 AndroidImageSlider動畫庫解析 為ViewPager的Page内容添加動畫,實作炫酷的互動效果 總結: GitHub上相關的ViewPager動畫的項目

總結:

整篇文章介紹的東西其實很簡單,隻是以前沒有研究過ViewPager.PageTransformer,使用簡單,但功能強大,position參數在動畫進行中相當重要,因為是實時的百分比,是以省去了自己不少計算,如果你需要為ViewPager自定義動畫,那麼選擇PageTransformer,對于本文的第二類巧妙動畫效果的介紹,看具體情況決定是否使用PageTransformer,如果position能很友善幫助動畫的計算,那是最好的,如果不是那麼你完全可以使用onPageScrolled來處理,源碼中也可看到,PageTransformer就是在onPageScroll中調用的。

使用時要注意,它隻支援3.0以上的系統。如果要相容,可以參考上面AndroidImageSlider的相容實作。在文章中也插入了不少ViewPager動畫項目的連結,也許不是使用PageTransformer,但也是一種思路的擴充,供大家參考。下一篇文章,我會介紹Fragment的動畫,大家敬請期待。

參考文獻:

官方文檔

Great animations with PageTransformer

Create ViewPager transitions

GitHub上相關的ViewPager動畫的項目

https://github.com/daimajia/AndroidImageSlider

https://github.com/inovex/ViewPager3D

輪循的ViewPager

https://github.com/antonyt/InfiniteViewPager

https://github.com/JakeWharton/salvage

https://github.com/Trinea/android-auto-scroll-view-pager

VerticalViewPager

https://github.com/JakeWharton/Android-DirectionalViewPager

https://github.com/LambergaR/VerticalViewPager

https://github.com/VenomVendor/AutoNotifyViewPager

https://github.com/Dreddik/AndroidTouchGallery

特效的ViewPager

https://github.com/kmshack/Android-ParallaxHeaderViewPager

https://github.com/andraskindler/parallaxviewpager

https://github.com/MoshDev/BackgroundViewPager

與ViewPager一起使用的導航:

https://github.com/astuetz/PagerSlidingTabStrip (不支援TextView顔色的變化)

https://github.com/jpardogo/PagerSlidingTabStrip (支援TextView顔色變化)

https://github.com/DSofter/SmoothTabIndicator

FragmentAnim

https://github.com/DesarrolloAntonio/FragmentTransactionExtended