叨叨ViewPager那些事儿(二)

作者: 苹果tree | 来源:发表于2018-07-24 11:14 被阅读240次

前言

上一篇叨叨ViewPager那些事儿(一)说了一点ViewPager概况,这篇打算说说实际应用。


从动画效果说起

先祭上一份谷歌官方的Transformer示例
效果如下


代码实现是这样

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)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        } else if (position <= 0) { // [-1,0]
            // Use the default slide transition when moving to the left page
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);

        } else if (position <= 1) { // (0,1]
            // Fade the page out.
            view.setAlpha(1 - position);

            // Counteract the default slide transition
            view.setTranslationX(pageWidth * -position);

            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

乍一看有点懵懂,一步一问 慢慢来

transformPage(View view, float position)两个参数是何含义


第一个参数为各页卡对象,第二个是各个页卡对于当前所展示页卡的相对位置,例如,当前页卡的position为0,下一张位置为1,前一张则为-1。而ViewPager滑动中,position的值是处于平滑变化中的,这就为我们处理动画提供了机会。

为何position < -1position > 1时设置可见度为0
如前问分析,position < -1position > 1指代页卡所处区间为[-Infinity,-1)和(1,+Infinity],在可见范围之外,从节省绘制资源的角度出发,自然可见度为0。

position (0,1]区间时为何要设置偏移度为(pageWidth * -position)
官方注释Counteract the default slide transition,抵消页面滑动时的默认偏移量。如页面处在中间时偏移量为0*width,移至右边为1*width,从中间往右移除时position0-->1渐变,默认偏移量为position*width

滑动动画的缩放效果如何计算
如效果图示,当下一张页卡相对位置从1-->0变化时,scale的变化方向为MIN_SCALE(m)-->1,不妨列个公式
(1-position)/(position-0)=(m-scale)/(scale-1)s=(1-position)/(1-position*m)(对。。跟示例代码不一样。。但是效果一样哦。。
也可以理解为1-scale=|(m-1)|/(1-0)*position,scale从1-->m,位置从0-->1,即每单位position的变化量为|(m-1)|/(1-0),乘上position得出变化量。

理论储备到位之后,自力更生的第一步就是,实践!
下边我们来写一个左右位移,同时展示三张卡片的动画,预想中效果大概是这样


根据设想计算,左右两边的页卡大小应为中间大页卡的0.9倍,左右页卡的偏移量约为±0.2倍页卡宽。
故设定MIN_Trans_INDEX = 0.2f,MIN_SCALE_INDEX = 0.9f。如上分析,我们只关心[-1,1]区间页卡的动画,
每单位position的scale变化量绝对值为(1-MIN_SCALE_INDEX)/(1-0),即1-scale=|position|*(1-MIN_SCALE_INDEX)/(1-0)scale=1-|position|*(1-MIN_SCALE_INDEX)
同理,每单位position的translationx变化量为pageWidth*(1-MIN_Trans_INDEX)/(1-0),即|0-translationx|=|position|*pageWidth*(1-MIN_Trans_INDEX)|translationx|=|position|*pageWidth*(1-MIN_Trans_INDEX),然而viewpager页卡滑动过程中的默认偏移量绝对值为pageWidth * position,故需在上式基础上减pageWidth * position,|translationx|=|position|*pageWidth*MIN_Trans_INDEX
计算完毕,写入代码后发现,效果是出来了,但是反应好像永远。慢半拍。当前页滑动到位后,下一页才出现,体验不太美妙,如下动图所示

查看代码后思考,应该是[-1,1]位置限定导致,左右两页分别滑动到-1和1时才开始做动画,而此时这两张页卡已经出现在屏幕上,所以看起来就像“慢了半拍”。
尝试增加一点“缓冲量”,改动如下

public class MyTransPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_Trans_INDEX = 0.2f;
    private static final float MIN_SCALE_INDEX = 0.9f;

    @Override
    public void transformPage(@NonNull View page, float position) {
        int pageWidth = page.getWidth();
        if (position < -1.1) { // [-Infinity,-1.1)
            // This page is way off-screen to the left.
            page.setAlpha(0);
        } else if (position <= 0) { // [-1.1,0]
            // Use the default slide transition when moving to the left page
            page.setAlpha(1);
            page.setTranslationX(-pageWidth * position * MIN_Trans_INDEX);
            page.setScaleX((1 - MIN_SCALE_INDEX) * position + 1);
            page.setScaleY((1 - MIN_SCALE_INDEX) * position + 1);
            Log.i("test", page.getTag()+"--"+((1 - MIN_SCALE_INDEX) * position + 1));
        } else if (position <= 1.1) { // (0,1.1]
            // Fade the page out.
            page.setAlpha(1);
            // Counteract the default slide transition
            page.setTranslationX(-pageWidth * position * MIN_Trans_INDEX);
            page.setScaleX(1 - (1 - MIN_SCALE_INDEX) * position);
            page.setScaleY(1 - (1 - MIN_SCALE_INDEX) * position);
        } else { // (1.1,+Infinity]
            // This page is way off-screen to the right.
            page.setAlpha(0);
        }
    }
}

再次运行。这才是想要的效果嘛


问题来了

之前遇到过一个现象,刷新ViewPager,调用notifyDataSetChanged(),如下。

诶,怎么肥事!左右两边的页卡去哪了!冷静一下,刷新时对当前页卡重绘,若不需滚动,则pageoffset始终为0,transformer的动画效果无法显示。看来要想平稳刷新,还需手动更新单条数据。
行动起来,更改如下逻辑

@Override
    public void onClick(View v) {
        if (v.getId() == R.id.tv_notify) {
            if (mCurPageIndex == 3) {//测试,代表逻辑需跳转到的页卡
                isNeedNotify = true;
            }
            //更新当前页卡数据
            updateViewPager(mCurPageIndex);
        }
    }
private void updateViewPager(int position) {
        if (isNeedNotify) {//需要滚动时,调用notifyDataSetChanged重走instantiateItem和destroyItem逻辑
            mPagerAdapter.notifyDataSetChanged();
            mViewPager.setCurrentItem(3);
            isNeedNotify = false;
        }
        //仅需更新当前页时则单独刷新当前页卡view
        MyViewPagerItem item = mPageItemList.get(position);
        if (item != null) {
            PageItemBean bean = new PageItemBean();
            bean.num = position;
            bean.tip = mContext.getString(R.string.num_tip, position + 1 + "");
            item.updateUI(bean);
        }
    }

重跑程序,问题解决。
为解决问题临时想的方案,是实现更新的一条思路但感觉不够优,欢迎各路大神指点。


最后

本想多写一点,但动画已经占了不少篇幅,为避免超长文先在这结束吧。这个系列会努力补充,欢迎多多指点和关注。

相关文章

  • 叨叨ViewPager那些事儿(二)

    前言 上一篇叨叨ViewPager那些事儿(一)说了一点ViewPager概况,这篇打算说说实际应用。 从动画效果...

  • 叨叨ViewPager那些事儿(一)

    前言 问ViewPager为何物?谷歌文档有云'Layout manager that allows the us...

  • 叨叨我家那些事儿

    我家上半年就还了2万多的帐。然后分文不存。我在家带两个娃。老公一个人上班挣钱。 我自己有记账的习惯,但是上半年还是...

  • 那些神神叨叨的事儿

    年少的时候喜欢三毛,除了羡慕她浪迹天涯的勇气、精彩的人生经历和洒脱的人生态度之外,也欣赏她有点神叨叨。比方说她描述...

  • 汽车销售那些事儿15

    《汽车销售那些事儿》目录 汽车销售那些事儿16 汽车销售那些事儿14 第二天颜颜休息,理直气壮地不用早起,跟温柔两...

  • 「碎语杂记」成家立业大事情

    这个周六,回了趟家。 老母亲还是叨叨那些事儿,问她孙子今年回来不回来。年前回去时问过这事儿了,只能再回答一次,回不...

  • 汽车销售那些事儿14

    《汽车销售那些事儿》目录 汽车销售那些事儿15 汽车销售那些事儿13 颜颜第二天仍旧爬起来去上班。 约了上次的那对...

  • 那些年,那些事儿(二)

    年龄越大,越喜欢回忆。回忆中,有永远不能忘却的美好,也有不愿提及的伤悲。所有的这些记忆,造就了人生的酸甜苦辣。 从...

  • 我被投诉了……”——医院里的那些事儿(3)

    文 | 攸宁 ID |lanyiweixin 医院里的那些事儿往期:“你眼里的医院”——医院里的那些事儿(二) 今...

  • 汽车销售那些事儿8

    《汽车销售那些事儿》目录 汽车销售那些事儿9 汽车销售那些事儿7 第二天早上晨会期间,一辆奔驰车停在店门口。前台崔...

网友评论

本文标题:叨叨ViewPager那些事儿(二)

本文链接:https://www.haomeiwen.com/subject/liktmftx.html