自定义View(三)---分析JazzViewPager

来源:互联网 发布:网络配线架打法图片 编辑:程序博客网 时间:2024/06/09 21:44

一、概述

JazzViewPager是什么?它其实是一种自定义View,继承ViewPager,普通v4包提供的ViewPager只能完成一些2d,的效果,如果想要完成更加酷的效果肯定需要我们自己设置(动画)。

二、Demo例子

xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <com.lw.myviewpager.other.JazzyViewPager         android:id="@+id/jvp"        android:layout_width="match_parent"        android:layout_height="wrap_content"     ></com.lw.myviewpager.other.JazzyViewPager></RelativeLayout>

java代码:

public class MainActivity extends Activity {    private JazzyViewPager jvp;    private int[] mImageViews = new int[]{            R.drawable.clothing_01,            R.drawable.clothing_02,            R.drawable.clothing_03,            R.drawable.clothing_04,            R.drawable.clothing_05,    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        jvp = (JazzyViewPager) findViewById(R.id.jvp);        jvp.setTransitionEffect(TransitionEffect.CubeOut);        jvp.setAdapter(new MyAdapter());    }    class MyAdapter extends PagerAdapter {        @Override        public int getCount() {            return mImageViews.length;        }        @Override        public boolean isViewFromObject(View view, Object object) {            return object == view;        }        @Override        public Object instantiateItem(ViewGroup container, int position) {            ImageView img = new ImageView(MainActivity.this);            img.setImageResource(mImageViews[position]);            img.setScaleType(ImageView.ScaleType.CENTER_CROP);            container.addView(img);            jvp.setObjectForPosition(img, position);            return img;        }        @Override        public void destroyItem(ViewGroup container, int position, Object object) {            container.removeView((View) object);        }    }}

三、Demo + JazzViewPager源码分析:

首先,看这行代码,主要设置一会ViewPager切换时的效果

    jvp.setTransitionEffect(TransitionEffect.CubeOut);
    public void setTransitionEffect(TransitionEffect effect) {        mEffect = effect;    }

将effect赋值给全局mEffect后,后面会通过switch判断,根据什么效果,开始执行什么动画。

switch (mEffect) {        case Standard:            break;        case Tablet:            animateTablet(mLeft, mRight, effectOffset);            break;        case CubeIn:            animateCube(mLeft, mRight, effectOffset, true);            break;        case CubeOut:            animateCube(mLeft, mRight, effectOffset, false);            break;        case FlipVertical:            animateFlipVertical(mLeft, mRight, positionOffset,                    positionOffsetPixels);            break;        case FlipHorizontal:            animateFlipHorizontal(mLeft, mRight, effectOffset,                    positionOffsetPixels);        case Stack:            animateStack(mLeft, mRight, effectOffset, positionOffsetPixels);            break;        case ZoomIn:            animateZoom(mLeft, mRight, effectOffset, true);            break;        case ZoomOut:            animateZoom(mLeft, mRight, effectOffset, false);            break;        case RotateUp:            animateRotate(mLeft, mRight, effectOffset, true);            break;        case RotateDown:            animateRotate(mLeft, mRight, effectOffset, false);            break;        case Accordion:            animateAccordion(mLeft, mRight, effectOffset);            break;        }

接着,当我们横向移动Viewpager的时候,会触发onPageScrolled(int position, float positionOffset,
int positionOffsetPixels)方法,这三个参数比较简单,自行打印log即可明白,在JazzViewPager的onPageScrolled中有两行比较重要的代码,如下,获取左右两边的View,

        mLeft = findViewFromObject(position);        mRight = findViewFromObject(position + 1);

点进去,看源码:

    public View findViewFromObject(int position) {        Object o = mObjs.get(Integer.valueOf(position));        if (o == null) {            return null;        }        PagerAdapter a = getAdapter();        View v;        for (int i = 0; i < getChildCount(); i++) {            v = getChildAt(i);            if (a.isViewFromObject(v, o))                return v;        }        return null;    }
private HashMap<Integer, Object> mObjs = new LinkedHashMap<Integer, Object>();

从源码中可以看出s首先根据position从一个增删快的map集合中获取一个object对象,那么这个object到底是什么类型,又是什么时候初始化数据的呢?再回到例子中MyAdapter中的instantiateItem方法,其中有一个代码如下:

jvp.setObjectForPosition(img, position);

其中img为图片ImageView对象,点进去看源码:

    public void setObjectForPosition(Object obj, int position) {        mObjs.put(Integer.valueOf(position), obj);    }

由此可以看出这个mObj是在这个时候进行初始化数据的。也就是说map集合里面保存的其实是每一个ImageView和对应position对应关系。再回到JazzViewPager的findViewFromObject()方法,从集合中取出object对象,判断是否为null,如果为null直接返回,否则依次遍历ViewPager子item,调用ViewPager的isViewFromObject方法判断是否为true,是返回v。就这样获取了当在左右移动时滑动的左右子view,接着就是根据之前传递过来的mEffect
进行动画了。如下:

    private void animateCube(View left, View right, float positionOffset,            boolean in) {        if (mState != State.IDLE) {            if (left != null) {                mRot = (in ? 90.0f : -90.0f) * positionOffset;                //设置旋转中心点                ViewHelper.setPivotX(left, left.getMeasuredWidth());                ViewHelper.setPivotY(left, left.getMeasuredHeight() * 0.5f);                //设置旋转角度                ViewHelper.setRotationY(left, mRot);            }            if (right != null) {                mRot = -(in ? 90.0f : -90.0f) * (1 - positionOffset);                ViewHelper.setPivotX(right, 0);                ViewHelper.setPivotY(right, right.getMeasuredHeight() * 0.5f);                ViewHelper.setRotationY(right, mRot);            }        }    }

判断左右子view是否为null,只有在不为null的条件下才会进动画。动画的执行比较简单,mRot是根据左右移动的便宜量来计算的。注意:这里的要用到ViewHelper需要导入nineoldandroids.jar包。

四、总结

JazzViewPager最终主要是根据属性动画来完成各种酷炫的效果的,过程中使用map来维持了Object和position的关系,在初始化的时候就在map集合中存入,由于ViewPager的懒加载机制,默认会加载下一页数据,因此left和right都有值。

源码下载

0 0
原创粉丝点击