本文沒有提供酷炫的動畫實現,而是分析理解如何使用自定義
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(這與ViewPager
的OnPageChangeListener
回調方法中的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 實現效果
自定義
PageTransformer
實現ViewPager
切換動畫的分析到此結束,知道原理后其他炫酷動畫效果自然就簡單了。