自定义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都有值。
源码下载
- 自定义View(三)---分析JazzViewPager
- 自定义View系列(三)View的绘制分析
- Android 自定义View (三)
- Android 自定义View (三)
- 自定义view(三)
- Android自定义View(三)
- 自定义View三
- 自定义view三
- 自定义View(三) 自定义itemCheckView
- 自定义View小示例(自定义View三)
- Android自定义View(三)继承View
- View详解之三自定义View
- Android 自定义View (三) ProgressBar
- android 自定义view(三)
- 自定义控件View(三)
- 自定义View(三)(Android群英传)
- android 自定义View 三 ---- LayoutInflater
- android自定义view(三)
- Android值数据读写在sd卡需要注意的事项
- java自学循环与选择性语句及表达式语句运算
- java设计模式:(策略模式)
- Android之文章权限的概念
- 在ActionBar上实现返回键和Toolbar共存
- 自定义View(三)---分析JazzViewPager
- hihocoder#1082 : 然而沼跃鱼早就看穿了一切
- Find 命令
- Intellij IDEA中Hibernate中创建的数据类中,无法发现table和列
- Ubuntu怎么从图形桌面切换到命令行界面
- 设计模式(3)-结构型-装饰模式(Decorator)
- [leetcode] 370. Range Addition 解题报告
- 附加 Sql Server 数据库文件mdf ldf 的 sql 语句(脚本)
- linux基础教程(9)权限机制