关于ViewPager.PageTransformer的一些理解
Posted microhex
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于ViewPager.PageTransformer的一些理解相关的知识,希望对你有一定的参考价值。
今天早上在看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
的关系为:
Count = limitN * 2 + 1
即需要viewPager保存(limitN * 2 + 1)个缓存状态view。为什么扯到这个东西呢?很简单,如果我们将setOffscreenPageLimit
设置为2,那么
void transformPage(@NonNull View page, float position);
这个方法中将会有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的,因此它走的是
2
中的if语句,postion的绝对值越变越大,因此alpha = position + 1.0f
越来越小,因此它就越来越透明了;我们需要的下一个next view的alpha的值会越来越大,因此它会越来越不透明了。
现在来一个比较复杂的一点的动画模式:
这个动画主要有位移、透明度、还有缩放动画,算上去比较复杂了吧。也还是来看一下比较源码:
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
以上是关于关于ViewPager.PageTransformer的一些理解的主要内容,如果未能解决你的问题,请参考以下文章