本文沒有提供酷炫的動(dòng)畫實(shí)現(xiàn)掩缓,而是分析理解如何使用自定義
PageTransformer
完成要想的效果。
1蓄诽、PageTransformer之position分析
從3.0開始功偿,ViewPager開始支持自定義切換動(dòng)畫,官方提供的接口為PageTransformer
座慰,因此只要實(shí)現(xiàn)該接口即可陨舱,PageTransformer
非常簡單,它只有一個(gè)方法:
/**
* 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()
方法的關(guān)鍵在于position的理解版仔,從doc注釋來看游盲,當(dāng)前選中的item的position永遠(yuǎn)是0(這與ViewPager
的OnPageChangeListener
回調(diào)方法中的position不同)误墓,被選中item的前一個(gè)為-1,被選中item的后一個(gè)為1益缎。** 其實(shí)這里文檔的描述并不是完全正確的驶臊,前后item position為-1和1的前提是你沒有給ViewPager
設(shè)置pageMargin
(通過調(diào)用viewPager.setPageMargin(int)
方法設(shè)置)**。如果你設(shè)置了pageMargin
哟沫,前后item的position需要分別加上(或減去遗淳,前減后加)一個(gè)偏移量(偏移量的計(jì)算方式為pageMargin / pageWidth
)。
在用戶滑動(dòng)界面的時(shí)候令哟,position是動(dòng)態(tài)變化的恼琼,下面以左滑為例:
- 選中item position:0->-1 - offset (pageMargin / pageWidth)
- 前一個(gè)item position:-1 - offset (pageMargin / pageWidth) -> -2 - offset (pageMargin / pageWidth),再往前就以此類推
- 后一個(gè)item position:1 + offset (pageMargin / pageWidth) -> 0屏富,再往后就以此類推
因此我們可以將position的值應(yīng)用于setAlpha()
, setTranslationX()
, 或者 setScaleY()
等等方法晴竞,從而實(shí)現(xiàn)自定義的動(dòng)畫效果。
2狠半、示例代碼
2.1 布局文件
先看下布局噩死,只有一個(gè)RelativeLayout
,內(nèi)部放置了一個(gè)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
可以展示多個(gè)Item已维,這里分別設(shè)置其以及其父布局的clipChildren
屬性為false。
2.2 滑動(dòng)技巧
ViewPager
滑動(dòng)還有一個(gè)小技巧瘤袖,我們都知道默認(rèn)情況下ViewPager
本身滑動(dòng)才可以切換頁面衣摩,所以就算屏幕上顯示了多個(gè)item,當(dāng)你滑動(dòng)未被選中的item時(shí)捂敌,ViewPager
也是無法切換頁面的艾扮。如果想擴(kuò)大滑動(dòng)區(qū)域可以給ViewPager
的父布局設(shè)置觸摸監(jiān)聽,并將觸摸事件交給ViewPager
處理占婉,這樣即使滑動(dòng)觸摸位置為未選中item泡嘴,ViewPager
仍然可以相應(yīng)滑動(dòng)了。代碼如下:
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);
//為了滑動(dòng)過程中逆济,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 實(shí)現(xiàn)效果
自定義
PageTransformer
實(shí)現(xiàn)ViewPager
切換動(dòng)畫的分析到此結(jié)束,知道原理后其他炫酷動(dòng)畫效果自然就簡單了奖慌。