高仿平行空间引导页视差效果实现

引言:学习平行空间引导页视差效果笔记,修改了一些小细节东西

按照惯例先扔上原视觉效果图

高仿平行空间引导页视差效果实现

一:视图效果分析:

效果步骤分析:
 1:一进来先进行一个透明动画,显示底图
 2:紧跟着显示执行一个动平移动画
 3:平移完成后执行翻转动画
 4:执行翻转动画的过程,背景颜色渐变

 实现思路分析:

 1:使用Viewpage,设置三个不同Fragment页面

 2:手机壳不动,其内部和外层,分别配了两个对应图片,然后分别执行位移动画

 3:监听Viewpage滑动事件,结合PageTransformer,实现滑动时动画效果执行

 4:怎么做的手机壳内View滑动时,不滑出手机壳外面

 法一)自定义Drawable(滑动的时候不断地将两张图片剪切并且拼接成一个Drawable。)
法二)HorizontalScrollView + 两张拼在一起的图片

  这边使用法二,设置HorizontalScrollView 和手机壳高度一致

   如何做到?相对于屏幕的宽高决定自己的宽高。
  用百分比布局。官方谷歌的百分比布局:只能相对于屏幕的宽度和高度
  这样会造成图片变形。所以只能自定义百分比布局(可以在谷歌的版本上直接修改少量代码。)这个就不在这边说明,因为我也是直接拿别人的代码,可以参考鸿洋大神的博客

二,代码实现:只挑其中重要地方,具体参考github地址

1.写入口代码创建Viewpage和适配器,把pageChangeListener传到transformer中,因为里面要判断当前是是第几个页面

高仿平行空间引导页视差效果实现

2:.创建Fragment和对应是适配器

需要传入布局id和页面的position,然后设置tag,在后面设置transformer动画效果时要用到

高仿平行空间引导页视差效果实现


高仿平行空间引导页视差效果实现

 page布局文件(具体看github)截取部分

高仿平行空间引导页视差效果实现

高仿平行空间引导页视差效果实现

自定义的HorizontalScrollView,进行事件拦截处理,

高仿平行空间引导页视差效果实现

*重点关键代码*

public class WelcompagerTransformer implements PageTransformer, OnPageChangeListener {

    private static final float ROT_MOD = -30f;
     private int pageIndex;
     private boolean pageChanged = true;


    /**
     * 此方法是滑动的时候每一个页面View都会调用该方法
     * view:当前的页面
     * position:当前滑动的位置
     * 视差效果:在View正常滑动的情况下,给当前View或者当前view里面的每一个子view来一个加速度
     * 而且每一个加速度大小不一样。
     */
    @Override
    public void transformPage(View view, float position) {
        ViewGroup v = (ViewGroup) view.findViewById(R.id.rl);
        final MyScrollView mscv =  v.findViewById(R.id.mscv);
        View bg1 = v.findViewById(R.id.imageView0);
        View bg2 = v.findViewById(R.id.imageView2);
        View bg_container = v.findViewById(R.id.bg_container);
        View iv_phone_bg = v.findViewById(R.id.iv_phone_bg);
        final View iv_titleTop = v.findViewById(R.id.iv_titleTop);
        int bg1_green = view.getContext().getResources().getColor(R.color.bg1_green);
        int bg2_blue = view.getContext().getResources().getColor(R.color.bg2_blue);
        Integer tag = (Integer) view.getTag();
        View parent = (View) view.getParent();

        //颜色估值器
        ArgbEvaluator evaluator = new ArgbEvaluator();
        int color = bg1_green;
        if (tag.intValue() == pageIndex) {//利用tag来判断页面position
            switch (pageIndex) {
                case 0:
                    color = (int) evaluator.evaluate(Math.abs(position), bg1_green, bg2_blue);
                    break;
                case 1:
                    color = (int) evaluator.evaluate(Math.abs(position), bg2_blue, bg1_green);
                    break;
                case 2:
                    color = (int) evaluator.evaluate(Math.abs(position), bg1_green, bg2_blue);
                    break;
            }
            //设置整个viewpager的背景颜色
            parent.setBackgroundColor(color);
        }
        if (position == 0) {//当前选中的Viewpage页面,position=0
            //pageChanged作用--解决问题:只有在切换页面的时候才展示平移动画,
            // 如果不判断则会只是移动一点点当前页面松开也会执行一次平移动画
            if (pageChanged) {
                bg1.setVisibility(View.VISIBLE);
                bg2.setVisibility(View.VISIBLE);
                ObjectAnimator animator_bg1 = ObjectAnimator.ofFloat(bg1, "translationX", 0,
                        -bg1.getWidth());
                animator_bg1.setDuration(600);
                animator_bg1.addUpdateListener(new AnimatorUpdateListener() {

                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        mscv.smoothScrollTo((int) (mscv.getWidth() * animation.getAnimatedFraction()), 0);
                        iv_titleTop.setAlpha(Math.abs(animation.getAnimatedFraction()));

                    }
                });
                animator_bg1.start();

                ObjectAnimator animator_bg2 = ObjectAnimator.ofFloat(bg2, "translationX", bg2.getWidth(), 0);
                animator_bg2.setDuration(600);
                animator_bg2.start();
                pageChanged = false;
            }
        } else if (position == -1 || position == 1) {//所有效果复原
            bg2.setTranslationX(0);
            bg1.setTranslationX(0);
            mscv.smoothScrollTo(0, 0);
            //在复原的时候隐藏bg2底图,实现两张图片平滑过渡,
            // 要不然会出现,图片两张图片都存在,然后闪一下bg2图片别移到屏幕外,然后在执行位移动画
            bg1.setVisibility(View.VISIBLE);
            bg2.setVisibility(View.INVISIBLE);
            iv_titleTop.setAlpha(0);
        } else if (position < 1 && position > -1) {
            final float width = bg1.getWidth();
            final float height = bg1.getHeight();
            final float rotation = ROT_MOD * position * -1.25f;
            //这里不去分别处理bg1、bg2,而是用包裹的父容器执行动画,目的是避免难以处理两个bg的属性位置恢复。
            bg_container.setPivotX(width * 0.5f);
            bg_container.setPivotY(height);
            bg_container.setRotation(rotation);

            mscv.setPivotX(width * 0.5f);
            mscv.setPivotY(height);
            mscv.setRotation(rotation);

            iv_phone_bg.setPivotX(width * 0.5f);
            iv_phone_bg.setPivotY(height);
            iv_phone_bg.setRotation(rotation);

        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        pageIndex = position;
        pageChanged = true;
    }

    @Override
    public void onPageScrollStateChanged(int state) {

  }

}

最后仿照后效果和github地址

高仿平行空间引导页视差效果实现

如有不妥,或者更好的意见欢迎大家提问,我会第一时间去修改和尝试,谢谢·~~~~~~