ViewPager的小知识点及源码解析

今天来说下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+的代码。如若有兴趣的话可以下载来看看,找到自己想要了解的一块再深入。源码下载


若有错误请留言指正,谢谢。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值