Android 使用自定義PageTransformer實現ViewPager切換動畫

本文沒有提供酷炫的動畫實現,而是分析理解如何使用自定義PageTransformer完成要想的效果。

1、PageTransformer之position分析

從3.0開始,ViewPager開始支持自定義切換動畫,官方提供的接口為PageTransformer,因此只要實現該接口即可,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 view, float position)

transformPage()方法的關鍵在于position的理解,從doc注釋來看,當前選中的item的position永遠是0(這與ViewPagerOnPageChangeListener回調方法中的position不同),被選中item的前一個為-1,被選中item的后一個為1。** 其實這里文檔的描述并不是完全正確的,前后item position為-1和1的前提是你沒有給ViewPager設置pageMargin(通過調用viewPager.setPageMargin(int)方法設置)**。如果你設置了pageMargin,前后item的position需要分別加上(或減去,前減后加)一個偏移量(偏移量的計算方式為pageMargin / pageWidth)。
在用戶滑動界面的時候,position是動態變化的,下面以左滑為例:

  • 選中item position:0->-1 - offset (pageMargin / pageWidth)
  • 前一個item position:-1 - offset (pageMargin / pageWidth) -> -2 - offset (pageMargin / pageWidth),再往前就以此類推
  • 后一個item position:1 + offset (pageMargin / pageWidth) -> 0,再往后就以此類推

因此我們可以將position的值應用于setAlpha(), setTranslationX(), 或者 setScaleY()等等方法,從而實現自定義的動畫效果。

2、示例代碼

2.1 布局文件

先看下布局,只有一個RelativeLayout,內部放置了一個ViewPager。

<RelativeLayout
    android:id="@+id/viewpager_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:clipChildren="false">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="200dp"
        android:layout_height="280dp"
        android:clipChildren="false"
        android:layout_centerInParent="true">
    </android.support.v4.view.ViewPager>
</RelativeLayout>

為了ViewPager可以展示多個Item,這里分別設置其以及其父布局的clipChildren屬性為false。

2.2 滑動技巧

ViewPager滑動還有一個小技巧,我們都知道默認情況下ViewPager本身滑動才可以切換頁面,所以就算屏幕上顯示了多個item,當你滑動未被選中的item時,ViewPager也是無法切換頁面的。如果想擴大滑動區域可以給ViewPager的父布局設置觸摸監聽,并將觸摸事件交給ViewPager處理,這樣即使滑動觸摸位置為未選中item,ViewPager仍然可以相應滑動了。代碼如下:

relativeLayout = (RelativeLayout) view.findViewById(R.id.viewpager_container);
relativeLayout.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return viewPager.onTouchEvent(event);
    }
});

2.3 自定義PageTransformer

class MyPageTransform implements ViewPager.PageTransformer {

    final float SCALE_MAX = 0.8f;
    final float ALPHA_MAX = 0.5f;

    @Override
    public void transformPage(View page, float position) {
        float scale = (position < 0)
                ? ((1 - SCALE_MAX) * position + 1)
                : ((SCALE_MAX - 1) * position + 1);
        float alpha = (position < 0)
                ? ((1 - ALPHA_MAX) * position + 1)
                : ((ALPHA_MAX - 1) * position + 1);
        //為了滑動過程中,page間距不變,這里做了處理
        if(position < 0) {
            ViewCompat.setPivotX(page, page.getWidth());
            ViewCompat.setPivotY(page, page.getHeight() / 2);
        } else {
            ViewCompat.setPivotX(page, 0);
            ViewCompat.setPivotY(page, page.getHeight() / 2);
        }
        ViewCompat.setScaleX(page, scale);
        ViewCompat.setScaleY(page, scale);
        ViewCompat.setAlpha(page, Math.abs(alpha));
    }
}

2.3 實現效果

device-2016-08-07-153455.gif

自定義PageTransformer實現ViewPager切換動畫的分析到此結束,知道原理后其他炫酷動畫效果自然就簡單了。

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

推薦閱讀更多精彩內容