今天来说下ViewPager相关知识点,现在市面上应用没有使用到ViewPager的相信已经很少了吧,我们就来对ViewPager中几个不常使用的方法做一些了解。
首先介绍几个在源码中查阅到的方法吧,之前完全没有留意过。
public void setPageMargin(int marginPixels) {
final int oldMargin = mPageMargin;
mPageMargin = marginPixels;
final int width = getWidth();
recomputeScrollPosition(width, width, marginPixels, oldMargin);
requestLayout();
}
public void setPageMarginDrawable(Drawable d) {
mMarginDrawable = d;
if (d != null) refreshDrawableState();
setWillNotDraw(d == null);
invalidate();
}
public void setPageMarginDrawable(@DrawableRes int resId) {
setPageMarginDrawable(getContext().getResources().getDrawable(resId));
}
这几个方法中上一个是可以给ViewPager页面间设置一个margin,下面两个方法可以给设置margin后产生空白处设置一个drawable,很简单明了。我最先以为设置这个drawable会一直显示在页面的边缘,但经过亲测之后发现只会在滑动的时候在两个页面之间显示出来,当滑动停止后会隐藏。当然你可以利用这个特点做一个精美的分隔线或者其它样式, 使你的应用别具一格。
下一个着重介绍的方法是 setPageTransformer(),此方法可以设置一个自定义的页面切换效果,google官方也写了两个不错的例子为我们提供参考,需要注意的是API版本必须大于11才有效。我们先来看看setPageTransformer的代码。
public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
if (Build.VERSION.SDK_INT >= 11) {
final boolean hasTransformer = transformer != null;
final boolean needsPopulate = hasTransformer != (mPageTransformer != null);
mPageTransformer = transformer;
setChildrenDrawingOrderEnabledCompat(hasTransformer);
if (hasTransformer) {
mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD;
} else {
mDrawingOrder = DRAW_ORDER_DEFAULT;
}
if (needsPopulate) populate();
}
}
该方法接收两个参数,第一个参数为一个布尔类型表示是否要用倒序,其实就是一个page中会有很多的子View,可以对它们进行一个绘制排序,个人理解由于一般绘制时间通常并没有那么长,几乎在一瞬间就完成,肉眼已经很难察觉我们可以直接设置为true即可。第二个参数为切换动画核心ViewPager的一个内部接口,该内部接口中只定义了一个方法。
public interface PageTransformer {
void transformPage(View page, float position);
}
第一个参数是当前可见页面,第二个参数为浮点数坐标,范围从-2.0 ~ 2.0表示,0始终表示为当前松手后抬起的可见页面,小于-1.0或大于1.0已完全不可见(如当前可见页的左边第二页或右边第二页),我们主要针对-1 ~ 1之间的值做相应动画。当我们从第一页滑动到第二页时,第一页的坐标从0变化到-1,第二页的坐标从1变化到0,我们可由拖动时不断变化的浮点数对page做一些动画。最先也想过回调中只有一个page,我们怎么可以同时作用于两个page完成如一个平移一个由小变大的动画呢, 实际测试是这个方法是会根据当前可见的page同时回调该方法,意思是当我们从第一页滑动到第二页的过程中有两个页面可见,我们只需对position的值进行判断就可以知道当前页面状态。如我们想从第一页滑动到第二页,在滑动到一半时停下来,此时两个页面各可见一半,坐标应为第一页-0.5f,第二页坐标0.5f,利用值的变化分别执行不同的动画,下面贴其中一个官方出的例子。
public class DepthPageTransformer implements ViewPager.PageTransformer {
//最小的缩放值
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
//获取页面宽度
int pageWidth = view.getWidth();
//完全不可见
if (position < -1) { // [-Infinity,-1)
view.setAlpha(0);
// -1 ~ 0
} else if (position <= 0) { // [-1,0]
//从左变滑出或划入时使用系统默认效果
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
// 0 ~ 1
} else if (position <= 1) { // (0,1]
// 设置透明度
view.setAlpha(1 - position);
// 抵消默认滑动效果,使page始终保持在页面中心
view.setTranslationX(pageWidth * -position);
// 将缩放范围设置在MIN_SCALE到1之间
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
//完全不可见
} else {
view.setAlpha(0);
}
}
}
该实现效果如下:
这个方法核心就是对不同范围的position作用不同的动画,Translate、Alpha、Rotate、Scale这四种效果组合应该能够完成你想要的效果了。其实图片浏览效果等都是可以用ViewPager加上这个方法实现。
另外我将ViewPager源码中所有的方法都添加了中文注释,变量和方法内详细内容并未一一解释,毕竟有3000+的代码。如若有兴趣的话可以下载来看看,找到自己想要了解的一块再深入。源码下载