今天早上在看hongyang的推送,說已經有了ViewPager2,是google的sample,位址為:https://github.com/googlesamples/android-viewpager2
裡面的動畫我看了一下,還是比較可以的,可以看下面動圖:

大概看了一下源碼,動畫是由
ViewPager2.PageTransformer
,其實跟
ViewPager.PageTransformer
接口一緻,然後查閱了一下資料,也算複習一下這個接口吧。
這個接口主要為:
public interface PageTransformer {
void transformPage(@NonNull View page, float position);
}
其中存在兩個參數,比較不好了解,第一個參數page我們可以了解為我們即将要轉換的對象,而對于position,我剛開始的了解為page的的目前的位置index,當看到postion是float的時候,我想我猜錯了。
雖然我不知道這個position是什麼意思,給的解釋也是模棱兩可的,然後我就打log記錄這個position值,大緻得出這樣的結論:
大緻的viewpager效果如下圖:
那麼在滑動的過程中:
前一個view的position變化 | 目前view的position變化 | 後一個view的position變化 | |
---|---|---|---|
目前view右滑時 | -1 ----> 0 | 0-------->1 | 1 ----> +∞ |
目前view左滑時 | -∞ ----> -1 | 0 -----> -1 | 1 ------->0 |
我們用動圖模拟一下此時的三個view的position的動态變化:
當我們向右移動時:
當我們向左移動時:
我們模拟viewpager的滑動,此時可以看到三個position的趨勢與上表是一緻的,是以對于這個position我可以這樣解釋:
目前我們的viewpager存在一個currentItem,就是目前的current position位置,我們記錄此時的坐标軸為0,那麼向右移動時,前一個view的position也是像右移動的,隻是它的坐标是由-1慢慢變大到0的,這種position的值是一個相對值,是相對于目前curerntItem的坐标位置的相對值;同理右邊的view也會向右移動,隻是它的相對值由1慢慢變得無限大。
同理,我們往左滑動時,這個position也是一個有方向的相對值。
還記得我們比較喜歡設定
viewpager.setOffscreenPageLimit
,它的意思就是螢幕之外的view保留幾個,我們也稱之為緩存view,其實這個limit的個數
limitN
與viewpager應該保持view的
Count
的關系為:
即需要viewPager儲存(limitN * 2 + 1)個緩存狀态view。為什麼扯到這個東西呢?很簡單,如果我們将
setOffscreenPageLimit
設定為2,那麼
這個方法中将會有5中不同的資料回調,分别是:
我們做個測試,将view加上id:
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
ImageView iv = new ImageView(getApplicationContext());
iv.setScaleType(ImageView.ScaleType.FIT_XY);
// 将id設定為 10000 + 目前的position
iv.setId(10000 + position);
ImageUtils.loadImage(imageList.get(position),iv);
container.addView(iv);
return iv;
}
然後我們在滑動的時候,列印一下日志:
@Override
public void transformPage(@NonNull View page, float position) {
Log.e("TAG", "page:" + page.getId() + "," + position);
}
我們看到的确存在5個類型的page值,說明我們的推斷是正确的。
我想我已經說清楚了這個position的位置,了解了這個數值的含義之後,我們來做個簡單的聯系,在滑動的過程中,viewpager的view透明度發生變化:
來看核心代碼,其實非常簡單:
@Override
public void transformPage(@NonNull View page, float position) {
float alpha = 0.0f;
if(0.0f <= position && position <= 1) { //1
alpha = 1.0f - position;
}else if (-1.0f <= position && position < 0.0f){ //2
alpha = position + 1.0f ;
}
page.setAlpha(alpha);
}
解釋如下:
我們隻考慮兩個view的透明度,是以隻需要考慮postion在 [-1. 1]的情況,而對于向左滑動時,目前的view的position的變化趨勢是由0 —> -1的,是以它走的是中的if語句,postion的絕對值越變越大,是以
2
越來越小,是以它就越來越透明了;我們需要的下一個next view的alpha的值會越來越大,是以它會越來越不透明了。
alpha = position + 1.0f
現在來一個比較複雜的一點的動畫模式:
這個動畫主要有位移、透明度、還有縮放動畫,算上去比較複雜了吧。也還是來看一下比較源碼:
1 @Override
2 public void transformPage(@NonNull View page, float position) {
3 int pagerWidth = boundViewPager.getWidth();
4 float horizontalOffsetBase = (pagerWidth - pagerWidth * CENTER_PAGE_SCALE) / 2;
5
6 if (position >= offscreenPageLimit || position <= -1) {
7 page.setVisibility(View.GONE);
8 } else {
9 page.setVisibility(View.VISIBLE);
10 }
11
12 if (position >= 0) {
13 float translationX = (horizontalOffsetBase - page.getWidth()) * position;
14 page.setTranslationX(translationX);
15 }
16
17 if (position > -1 && position < 0) {
18 float rotation = position * 30;
19 page.setRotation(rotation);
20 page.setAlpha((position * position * position + 1));
21
22 } else if (position > offscreenPageLimit) {
23 page.setAlpha((float) (1 - position + Math.floor(position)));
24
25 } else {
26 page.setRotation(0);
27 page.setAlpha(1);
28 }
29
30
31 if (position == 0) {
32 page.setScaleX(CENTER_PAGE_SCALE);
33 page.setScaleY(CENTER_PAGE_SCALE);
34 } else {
35 float scaleFactor = Math.min(CENTER_PAGE_SCALE - position * 0.1f, CENTER_PAGE_SCALE);
36 page.setScaleY(scaleFactor);
37 page.setScaleY(scaleFactor);
38 }
39 }
上面的 boundViewPager就是我們傳入的viewpager,主要的作用就是擷取limitpage,CENTER_PAGE_SCALE我設定的是0.8f.下面開始分析一下:
- 從第6行開始 主要是隻顯示offscreenPageLimit + 1個view,其他的view都隐藏掉。
- 第12行主要是設定下一個view的位移動畫,使它慢慢向左偏移,這個很好了解。
- 第17行主要是我要實作翻頁的效果的動畫,主要時設定目前頁的旋轉動畫和透明度動畫。
- 第31行開始,主要就是設定view的縮放動畫了。
從這裡看,設定這種動畫還是比較容易的,隻要你分開去分析,去做,應該是很簡單的。
對于這個PageTransformer,基本原理大家都知道了。其實它還可以做一些比較好看的動畫,我在網上摘了一些,供自己做個筆記吧:
&nbsbp;
這是這篇文章來的,大牛寫的非常好,大家可以參考一下:
https://blog.csdn.net/u012702547/article/details/52334161
還有github上面開源的庫:
這個庫來自大神:https://github.com/OCNYang/PageTransformerHelp 他給出的效果有很多,了解了這個position,相信大家會很快了解每個PageTransformer的作用。大家可以去star一下。?
好了,也寫了好長時間了,有不足的地方希望大家指出。
參考文章:
- https://blog.csdn.net/u012702547/article/details/52334161
- https://blog.csdn.net/shedoor/article/details/78957852
- http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1030/1870.html
- https://www.cnblogs.com/lang-yu/p/6082791.html
- https://www.cnblogs.com/prophet-it/p/7544673.html