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

一、概述

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值