今天在github里看到一个3D效果的ViewPager,感觉做出来的ViewPager滑动的时候效果十分的炫,就check out下来研究了一下如何实现的,以及如何使用,将整个ViewPager稍加修改后(主要是处理了一下与项目中其它控滑动控件的事件冲突)后,应用到了自己现在项目中。感觉这个效果真的非常的不错,现在把自己写的一个Demo分享出来。

 下面是这个ViewPager嵌入到项目中的效果图:

 

修改以后,在切换ViewPager时会有立体感,会为自己的应用增色不少。下面把使用的Demo发出来,其实与使用普通的ViewPager完全一样,只不过好像只能用PagerAdapter及其子类Adapter为它填充数据。

1.ViewPager3D源码:

public class ViewPager3D extends ViewPager
{/*** maximum overscroll rotation of the children is 90 divided by this value*/final static float DEFAULT_OVERSCROLL_ROTATION = 2f;/*** maximum z distance to translate child view*/final static int DEFAULT_OVERSCROLL_TRANSLATION = 150;/*** maximum z distanze during swipe*/final static int DEFAULT_SWIPE_TRANSLATION = 100;/*** maximum rotation during swipe is 90 divided by this value*/final static float DEFAULT_SWIPE_ROTATION = 3;/*** duration of overscroll animation in ms*/final private static int DEFAULT_OVERSCROLL_ANIMATION_DURATION = 400;/*** if true alpha of children gets animated during swipe and overscroll*/final private static boolean DEFAULT_ANIMATE_ALPHA = true;@SuppressWarnings("unused")private final static String DEBUG_TAG = ViewPager.class.getSimpleName();private final static int INVALID_POINTER_ID = -1;private final static double RADIANS = 180f / Math.PI;/*** @author renard*/private class OverscrollEffect{private float mOverscroll;private Animator mAnimator;/*** @param deltaDistance [0..1] 0->no overscroll, 1>full overscroll*/public void setPull(final float deltaDistance){mOverscroll = deltaDistance;invalidateVisibleChilds();}/*** called when finger is released. starts to animate back to default* position*/private void onRelease(){if (mAnimator != null && mAnimator.isRunning()){mAnimator.addListener(new AnimatorListener(){@Overridepublic void onAnimationStart(Animator animation){}@Overridepublic void onAnimationRepeat(Animator animation){}@Overridepublic void onAnimationEnd(Animator animation){startAnimation(0);}@Overridepublic void onAnimationCancel(Animator animation){}});mAnimator.cancel();}else{startAnimation(0);}}private void startAnimation(final float target){mAnimator = ObjectAnimator.ofFloat(this, "pull", mOverscroll, target);mAnimator.setInterpolator(new DecelerateInterpolator());final float scale = Math.abs(target - mOverscroll);mAnimator.setDuration((long) (mOverscrollAnimationDuration * scale));mAnimator.start();}private boolean isOverscrolling(){if (mScrollPosition == 0 && mOverscroll < 0){return true;}if (getAdapter() != null){final boolean isLast = (getAdapter().getCount() - 1) == mScrollPosition;if (isLast && mOverscroll > 0){return true;}}return false;}}final private OverscrollEffect mOverscrollEffect = new OverscrollEffect();final private Camera mCamera = new Camera();private OnPageChangeListener mScrollListener;private float mLastMotionX;private int mActivePointerId;private int mScrollPosition;private float mScrollPositionOffset;private int mScrollPositionOffsetPixels;final private int mTouchSlop;private float mOverscrollRotation;private float mSwipeRotation;private int mOverscrollTranslation;private int mSwipeTranslation;private int mOverscrollAnimationDuration;private boolean mAnimateAlpha;private Rect mTempTect = new Rect();public ViewPager3D(Context context, AttributeSet attrs){super(context, attrs);setStaticTransformationsEnabled(true);final ViewConfiguration configuration = ViewConfiguration.get(context);mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);super.setOnPageChangeListener(new MyOnPageChangeListener());init(attrs);}private void init(AttributeSet attrs){TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ViewPager3D);mOverscrollRotation = a.getFloat(R.styleable.ViewPager3D_overscroll_rotation, DEFAULT_OVERSCROLL_ROTATION);mSwipeRotation = a.getFloat(R.styleable.ViewPager3D_swipe_rotation, DEFAULT_SWIPE_ROTATION);mSwipeTranslation = a.getInt(R.styleable.ViewPager3D_swipe_translation, DEFAULT_SWIPE_TRANSLATION);mOverscrollTranslation = a.getInt(R.styleable.ViewPager3D_overscroll_translation,DEFAULT_OVERSCROLL_TRANSLATION);mOverscrollAnimationDuration = a.getInt(R.styleable.ViewPager3D_overscroll_animation_duration,DEFAULT_OVERSCROLL_ANIMATION_DURATION);mAnimateAlpha = a.getBoolean(R.styleable.ViewPager3D_animate_alpha, DEFAULT_ANIMATE_ALPHA);a.recycle();}public boolean isAnimateAlpha(){return mAnimateAlpha;}public void setAnimateAlpha(boolean mAnimateAlpha){this.mAnimateAlpha = mAnimateAlpha;}public int getOverscrollAnimationDuration(){return mOverscrollAnimationDuration;}public void setOverscrollAnimationDuration(int mOverscrollAnimationDuration){this.mOverscrollAnimationDuration = mOverscrollAnimationDuration;}public int getSwipeTranslation(){return mSwipeTranslation;}public void setSwipeTranslation(int mSwipeTranslation){this.mSwipeTranslation = mSwipeTranslation;}public int getOverscrollTranslation(){return mOverscrollTranslation;}public void setOverscrollTranslation(int mOverscrollTranslation){this.mOverscrollTranslation = mOverscrollTranslation;}public float getSwipeRotation(){return mSwipeRotation;}public void setSwipeRotation(float mSwipeRotation){this.mSwipeRotation = mSwipeRotation;}public float getOverscrollRotation(){return mOverscrollRotation;}public void setOverscrollRotation(float mOverscrollRotation){this.mOverscrollRotation = mOverscrollRotation;}@Overridepublic void setOnPageChangeListener(OnPageChangeListener listener){mScrollListener = listener;};private void invalidateVisibleChilds(){for (int i = 0; i < getChildCount(); i++){final View childAt = getChildAt(i);childAt.getLocalVisibleRect(mTempTect);final int area = mTempTect.width() * mTempTect.height();if (area > 0){childAt.invalidate();}}invalidate();}private class MyOnPageChangeListener implements OnPageChangeListener{@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels){if (mScrollListener != null){mScrollListener.onPageScrolled(position, positionOffset, positionOffsetPixels);}mScrollPosition = position;mScrollPositionOffset = positionOffset;mScrollPositionOffsetPixels = positionOffsetPixels;// Log.i(DEBUG_TAG, "mScrollPosition = " + position + " offset = " + String.format("%f.2", positionOffset));// Log.i(DEBUG_TAG, "onPageScrolled");invalidateVisibleChilds();}@Overridepublic void onPageSelected(int position){if (mScrollListener != null){mScrollListener.onPageSelected(position);}}@Overridepublic void onPageScrollStateChanged(final int state){if (mScrollListener != null){mScrollListener.onPageScrollStateChanged(state);}if (state == SCROLL_STATE_IDLE){mScrollPositionOffset = 0;}}}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev){final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;switch (action){case MotionEvent.ACTION_DOWN:{mLastMotionX = ev.getX();mActivePointerId = MotionEventCompat.getPointerId(ev, 0);break;}case MotionEventCompat.ACTION_POINTER_DOWN:{final int index = MotionEventCompat.getActionIndex(ev);final float x = MotionEventCompat.getX(ev, index);mLastMotionX = x;mActivePointerId = MotionEventCompat.getPointerId(ev, index);break;}}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent ev){boolean callSuper = false;final int action = ev.getAction();switch (action){case MotionEvent.ACTION_DOWN:{callSuper = true;mLastMotionX = ev.getX();mActivePointerId = MotionEventCompat.getPointerId(ev, 0);break;}case MotionEventCompat.ACTION_POINTER_DOWN:{callSuper = true;final int index = MotionEventCompat.getActionIndex(ev);final float x = MotionEventCompat.getX(ev, index);mLastMotionX = x;mActivePointerId = MotionEventCompat.getPointerId(ev, index);break;}case MotionEvent.ACTION_MOVE:{if (mActivePointerId != INVALID_POINTER_ID){// Scroll to follow the motion eventfinal int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);final float x = MotionEventCompat.getX(ev, activePointerIndex);final float deltaX = mLastMotionX - x;final int width = getWidth();final int widthWithMargin = width + getPageMargin();final int lastItemIndex = getAdapter().getCount() - 1;final int currentItemIndex = getCurrentItem();final float leftBound = Math.max(0, (currentItemIndex - 1) * widthWithMargin);final float rightBound = Math.min(currentItemIndex + 1, lastItemIndex) * widthWithMargin;if (mScrollPositionOffset == 0){if (currentItemIndex == 0){if (leftBound == 0){final float over = deltaX + mTouchSlop;mOverscrollEffect.setPull(over / width);}}else if (lastItemIndex == currentItemIndex){if (rightBound == lastItemIndex * widthWithMargin){final float over = deltaX - mTouchSlop;mOverscrollEffect.setPull(over / width);}}}else{mLastMotionX = x;}}else{mOverscrollEffect.onRelease();}break;}case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:{callSuper = true;mActivePointerId = INVALID_POINTER_ID;mOverscrollEffect.onRelease();break;}case MotionEvent.ACTION_POINTER_UP:{final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);if (pointerId == mActivePointerId){// This was our active pointer going up. Choose a new// active pointer and adjust accordingly.final int newPointerIndex = pointerIndex == 0 ? 1 : 0;mLastMotionX = ev.getX(newPointerIndex);mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);callSuper = true;}break;}}if (mOverscrollEffect.isOverscrolling() && !callSuper){return true;}else{try{return super.onTouchEvent(ev);}catch (IllegalArgumentException ignore){}catch (ArrayIndexOutOfBoundsException ignore){}return false;}}@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t){if (child.getWidth() == 0){return false;}final boolean isFirstOrLast = mScrollPosition == 0 || (mScrollPosition == (getAdapter().getCount() - 1));if (mOverscrollEffect.isOverscrolling() && isFirstOrLast){final float dx = getWidth() / 2;final int dy = getHeight() / 2;t.getMatrix().reset();final float translateZ = (float) (mOverscrollTranslation * Math.sin(Math.PI* Math.abs(mOverscrollEffect.mOverscroll)));final float degrees = 90 / mOverscrollRotation- (float) ((RADIANS * Math.acos(mOverscrollEffect.mOverscroll)) / mOverscrollRotation);mCamera.save();mCamera.rotateY(degrees);mCamera.translate(0, 0, translateZ);mCamera.getMatrix(t.getMatrix());mCamera.restore();t.getMatrix().preTranslate(-dx, -dy);t.getMatrix().postTranslate(dx, dy);if (mAnimateAlpha){t.setTransformationType(Transformation.TYPE_BOTH);t.setAlpha((FloatMath.sin((float) ((1 - Math.abs(mOverscrollEffect.mOverscroll)) * Math.PI / 2))));}return true;}else if (mScrollPositionOffset > 0){final float dx = getWidth() / 2;final float dy = getHeight() / 2;double degrees = 0;child.getLocalVisibleRect(mTempTect);if (mTempTect.left >= mScrollPositionOffsetPixels){if (mAnimateAlpha){t.setTransformationType(Transformation.TYPE_BOTH);t.setAlpha((FloatMath.sin((float) (mScrollPositionOffset * Math.PI / 2))));}// right sidedegrees = (90 / mSwipeRotation) - (RADIANS * Math.acos(mScrollPositionOffset)) / mSwipeRotation;}else if (mTempTect.left == 0){if (mAnimateAlpha){t.setTransformationType(Transformation.TYPE_BOTH);t.setAlpha((FloatMath.sin((float) (mScrollPositionOffset * Math.PI / 2 + Math.PI / 2))));}// left sidedegrees = -(90 / mSwipeRotation) + (RADIANS * Math.acos(1 - mScrollPositionOffset)) / mSwipeRotation;}final float translateZ = (mSwipeTranslation * FloatMath.sin((float) ((Math.PI) * mScrollPositionOffset)));// Log.i(DEBUG_TAG, visibleRect.left+ ", " + mScrollPositionOffsetPixels + ", degress = "+// String.format("%f.2", degrees));t.getMatrix().reset();mCamera.save();mCamera.rotateY((float) degrees);mCamera.translate(0, 0, translateZ);mCamera.getMatrix(t.getMatrix());mCamera.restore();// pivot point is center of childt.getMatrix().preTranslate(-dx, -dy);t.getMatrix().postTranslate(dx, dy);// child.invalidate();return true;}return false;}
}

2.Activity中使用ViewPager3D

package com.example.pageradapterdemo;import java.util.ArrayList;import android.os.Bundle;
import android.support.v4.app.FragmentActivity;import com.focustech.common.widget.scrollviewpager.ViewPager3D;public class MainActivity extends FragmentActivity
{private ViewPager3D mViewPager;private CommonFragmentAdapter mAdapter;private ArrayList<MyFragment> mList;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initData();initView();}private void initView(){mViewPager = (ViewPager3D) findViewById(R.id.viewpager);mAdapter = new CommonFragmentAdapter(MainActivity.this, getSupportFragmentManager(), mList);mViewPager.setAdapter(mAdapter);}private void initData(){mList = new ArrayList<MyFragment>();MyFragment layout1 = new MyFragment("One Fragment");MyFragment layout2 = new MyFragment("Two Fragment");MyFragment layout3 = new MyFragment("Three Fragment");mList.add(layout1);mList.add(layout2);mList.add(layout3);}
}

3.CommonFragemntAdapter为ViewPager3D填充Fragment

public class CommonFragmentAdapter extends FragmentStatePagerAdapter
{private ArrayList<MyFragment> fragmentList;public CommonFragmentAdapter(Activity activity, FragmentManager fm, ArrayList<MyFragment> fragmentList){super(fm);this.fragmentList = fragmentList;}@Overridepublic Fragment getItem(int arg0){return fragmentList.get(arg0);}@Overridepublic int getCount(){return fragmentList.size();}@Overridepublic void destroyItem(ViewGroup container, int position, Object object){super.destroyItem(container, position, object);}
}

总结:将ViewPager3D当作一个普通的ViewPager来使用即可。

android自定义ViewPager之——3D效果应用相关推荐

  1. 微信小程序手把手教你实现类似Android中ViewPager控件效果

    微信小程序手把手教你实现类似Android中ViewPager控件效果 前言 需求分析 头部TAB 滑动的内容部分 最终版本 尾巴 前言 在做Android开发的时候,ViewPager是开发者使用频 ...

  2. Android 自定义 HorizontalScrollView 横向滑动效果

    自从Gallery被谷歌废弃以后,Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的效果.的确HorizontalScrollView可以实现Gal ...

  3. android双重for循环,Android实现ViewPager无限循环效果(二)

    本文实例为大家分享了Android实现ViewPager无限循环效果的第二种方式,供大家参考,具体内容如下 原理:在Adapter中将getCount设置为无限大 package com.xiaoma ...

  4. android中仿qq最新版抽屉,Android 自定义View实现抽屉效果

    Android 自定义View实现抽屉效果 说明 这个自定义View,没有处理好多点触摸问题 View跟着手指移动,没有采用传统的scrollBy方法,而是通过不停地重新布局子View的方式,来使得子 ...

  5. Android 自定义 圆环,Android自定义view实现圆环效果实例代码

    先上效果图,如果大家感觉不错,请参考实现代码. 重要的是如何实现自定义的view效果 (1)创建类,继承view,重写onDraw和onMesure方法 public class CirclePerc ...

  6. android波纹效果弹窗,Android自定义View实现波纹效果

    Android自定义View实现波纹效果 时间:2017-05-27     来源:移动互联网学院 1.引言:随着Android智能手机的普及,Android应用得到了大力支持,而Android应用的 ...

  7. android 循环弹幕,Android自定义View实现弹幕效果

    原标题:Android自定义View实现弹幕效果 在很多视频直播中都有弹幕功能,而安卓上没有简单好用的弹幕控件,本文介绍一个自定义弹幕view的demo. 效果图: 思路: 自定义Textitem类表 ...

  8. android下雨动画效果,Android 自定义View(二) 下雨效果

    Rain.gif Android 自定义View(二) 下雨效果 一 实现思路, 雨点用线段表示,通过控制线段的大小和宽度来表示不同的线段. 一个雨点下雨的过程可以表示为一条直线,一次雨点在下雨的过程 ...

  9. android功能相同的view,Android自定义View实现扫描效果

    本文实例为大家分享了Android自定义View实现扫描效果的具体代码,供大家参考,具体内容如下 演示效果如下: 实现内容: 1.控制动画是竖向或者横向 2.控制动画初始是从底部/左边开始,或者从上边 ...

  10. android如何自定义viewpager,Android自定义ViewPager实现个性化的图片切换效果

    第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主界面通通ViewPager,以及图片切换也抛弃了ImageSwitch之类的,开始让ViewPager来做.时间长了,ViewPager的 ...

最新文章

  1. 个人博客作业week7
  2. android 新特性笔记
  3. php经典实例使用正则动态修改配置文件
  4. java byte 转 c_C 和 Java 之间的byte数据的转换问题
  5. 试着用React写项目-利用react-router解决跳转路由等问题(二)
  6. airflow时区问题
  7. 用 SQL 脚本读取Excel 中的sheet数量及名称
  8. MySQL 入门(三)—— MySQL数据类型
  9. 流水作业c语言代码,C语言流水灯
  10. vscode 字体大小和行间距设置
  11. keevi源地址_2019年越狱源地址排行是怎样的?
  12. Win10家庭中文版如何添加本地用户
  13. 在ENSP中配置DHCP服务器
  14. 第十六届全国大学生智能汽车比赛—摄像头算法控制总结
  15. 数据太多?3款免费数据分析软件,分分钟解决
  16. ubuntu下定时自动备份数据库
  17. a55计算机主板,高性价比APU主板!AMD A55主板对比评测
  18. 程序员如何与产品撕逼
  19. 基于有源钳位三电平的有源电力滤波器(ANPC-APF)MATLAB仿真,包括自建的DSOGI锁相模块和PQ谐波检测模块
  20. 数据结构 实验7 二叉树的应用

热门文章

  1. uV胶点胶机器人_解析手机用粘合剂十大用胶点
  2. 论文阅读-可变形卷积网络:Deformable Convolutional Networks
  3. python数据分析之(7)简单绘图pylab
  4. node.js(一)基础介绍
  5. 全网首发!超全SparseR-CNN实战教程
  6. CVPR2021 Oral|开放世界中的目标检测
  7. STDN:Scale-Transferrable Object Detection 论文解析
  8. 谷歌Deep Dream解析(附源代码,可以直接运行)
  9. 「平衡树splay」学习笔记#1
  10. 聊聊我怎么系统学习Linux技能并快速提高的