叨叨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那些事儿(二)

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