android ViewPager是一個经常要用到的组件,但android系统本身为我们提供的ViewPager是没有任何效果的,只能是一页一页的滑动,这样会让人感觉很死板,在看一些知名大公司的App时,看到了他们的ViewPager在滑动到最开始或者最后的时候是有一个弹性效果的,使用起来感觉非常的好,于是乎就是百度搜了一下,在StackOverflow中看到一篇文章就是讲如何实现这个效果的。

  先看下效果图:滑动到最后一页时仍然可以拉动……

代码如下:

 package com.example.myviewpager;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Camera;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewConfigurationCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Transformation;import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.animation.ObjectAnimator;public class BounceBackViewPager extends ViewPager
{/*** maximum z distance to translate child view*/final static int DEFAULT_OVERSCROLL_TRANSLATION = 500;/*** duration of overscroll animation in ms*/final private static int DEFAULT_OVERSCROLL_ANIMATION_DURATION = 400;@SuppressWarnings("unused")private final static String DEBUG_TAG = ViewPager.class.getSimpleName();private final static int INVALID_POINTER_ID = -1;/**** @author renard, extended by Piotr Zawadzki**/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(mLastPosition);}/*** 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;}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;final private int mTouchSlop;private float mOverscrollTranslation;private int mOverscrollAnimationDuration;public BounceBackViewPager(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.BounceBackViewPager);mOverscrollTranslation = a.getDimension(R.styleable.BounceBackViewPager_overscroll_translation_bounce,DEFAULT_OVERSCROLL_TRANSLATION);mOverscrollAnimationDuration = a.getInt(R.styleable.BounceBackViewPager_overscroll_animation_duration_bounce,DEFAULT_OVERSCROLL_ANIMATION_DURATION);a.recycle();}public int getOverscrollAnimationDuration(){return mOverscrollAnimationDuration;}public void setOverscrollAnimationDuration(int mOverscrollAnimationDuration){this.mOverscrollAnimationDuration = mOverscrollAnimationDuration;}public float getOverscrollTranslation(){return mOverscrollTranslation;}public void setOverscrollTranslation(int mOverscrollTranslation){this.mOverscrollTranslation = mOverscrollTranslation;}@Overridepublic void setOnPageChangeListener(OnPageChangeListener listener){mScrollListener = listener;};private void invalidateVisibleChilds(final int position){for (int i = 0; i < getChildCount(); i++){getChildAt(i).invalidate();}// this.invalidate();// final View child = getChildAt(position);// final View previous = getChildAt(position - 1);// final View next = getChildAt(position + 1);// if (child != null) {// child.invalidate();// }// if (previous != null) {// previous.invalidate();// }// if (next != null) {// next.invalidate();// }}private int mLastPosition = 0;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;mLastPosition = position;invalidateVisibleChilds(position);}@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){try{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);}catch (IllegalArgumentException e){e.printStackTrace();return false;}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();return false;}}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev){try{return super.dispatchTouchEvent(ev);}catch (IllegalArgumentException e){e.printStackTrace();return false;}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();return false;}}@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 float oldScrollX = getScrollX();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;final float scrollX = oldScrollX + deltaX;if (mScrollPositionOffset == 0){if (scrollX < leftBound){if (leftBound == 0){final float over = deltaX + mTouchSlop;mOverscrollEffect.setPull(over / width);}}else if (scrollX > rightBound){if (rightBound == lastItemIndex * widthWithMargin){final float over = scrollX - rightBound - 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{return super.onTouchEvent(ev);}}@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t){if (child.getWidth() == 0){return false;}final int position = child.getLeft() / child.getWidth();final boolean isFirstOrLast = position == 0 || (position == getAdapter().getCount() - 1);if (mOverscrollEffect.isOverscrolling() && isFirstOrLast){final float dx = getWidth() / 2;final int dy = getHeight() / 2;t.getMatrix().reset();final float translateX = (float) mOverscrollTranslation* (mOverscrollEffect.mOverscroll > 0 ? Math.min(mOverscrollEffect.mOverscroll, 1) : Math.max(mOverscrollEffect.mOverscroll, -1));mCamera.save();mCamera.translate(-translateX, 0, 0);mCamera.getMatrix(t.getMatrix());mCamera.restore();t.getMatrix().preTranslate(-dx, -dy);t.getMatrix().postTranslate(dx, dy);if (getChildCount() == 1){this.invalidate();}else{child.invalidate();}return true;}return false;}
}

自定义属性如下:

<declare-styleable name="BounceBackViewPager"><attr name="overscroll_translation_bounce" format="dimension" /><!-- Duration of animation when user releases the over scroll. Default is 400 ms. --><attr name="overscroll_animation_duration_bounce" format="integer" /></declare-styleable>

android自定义ViewPager之——水平滑动弹性效果相关推荐

  1. android fragment界面滑动切换效果,Android App中使用ViewPager+Fragment实现滑动切换效果...

    在android应用中,多屏滑动是一种很常见的风格,没有采用viewpager的代码实现会很长,如果采用ViewPager,代码就会短很多,但是使用ViewPager也有弊端:需要导入android- ...

  2. android 仿ios动画效果代码,Android仿IOS上拉下拉弹性效果的实例代码

    用过iphone的朋友相信都体验过页面上拉下拉有一个弹性的效果,使用起来用户体验很好:Android并没有给我们封装这样一个效果,我们来看下在Android里如何实现这个效果.先看效果,感觉有些时候还 ...

  3. android 自定义view滚动条,Android自定义View实现等级滑动条的实例

    Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点: 绘制点的时候把X值存到集合中. 然后绘制背景图片,以及图片上的数字. 点击事件down的时候 ...

  4. android dialog 自定义布局,Android自定义Dialog实现加载对话框效果

    前言 最近开发中用到许多对话框,之前都是在外面的代码中创建AlertDialog并设置自定义布局实现常见的对话框,诸如更新提示等含有取消和删除两个按钮的对话框我们可以通过代码创建一个AlertDial ...

  5. Android 自定义ViewPager设置屏蔽左右滑动事件

    只要有欲望,就应该有奋斗的心.... 屏蔽左右滑动事件的viewPager public class CustomNoScrollViewPager extends ViewPager{private ...

  6. [Android]使用ViewPager实现图片滑动展示

    在淘宝等电商的APP首页经常能看到大幅的广告位,通常有多幅经常更新的图片用于展示促销信息,如下图所示: 通常会自动滚动,也可以根据手势滑动.我没有研究过人家的APP是通过什么实现的,可能有第三方已经封 ...

  7. android qq弹出菜单,Android开发实现qqminihd 左右滑动菜单效果

    类型:编程工具大小:13.8M语言:英文 评分:5.5 标签: 立即下载 观察qqminihd界面,发现其界面能够左右滑动来实现两侧菜单效果. 自定义Layout:ScrollLayout.java ...

  8. Android 使用ViewPager实现view轮播效果,单个item分页样式,多个item分页样式,横向listview

    效果 单个item样式 多个item样式 横向item 自定义viewpager--可开关切换动画 public class NoAnimationViewPager extends ViewPage ...

  9. Android仿今日头条图片滑动退出效果

    资源下载(2C币) 逛CSDN的时候,看到几篇写仿今日头条图片滑动退出效果的文章,闲着无聊便想着也给自己项目加上,实现的思路有很多种,本着就近原则选了一篇与自己思路相近的文章结合自己的实践总结一下. ...

  10. Android禁止ViewPager的左右滑动

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/40744287 有时候在开发中会遇到一些"诡异"的要求,比方在V ...

最新文章

  1. Python IDLE快捷键一览
  2. 数据关系模式设计的标准化
  3. MATLAB应用实战系列NSGA-II多目标优化算法原理及应用实例(附MATLAB代码)
  4. 五、【线性表】线性表的链式表示和实现
  5. boost::owner_equal_to相关的测试程序
  6. C++手动实现库函数
  7. CVE-2019-8660 iMessage 漏洞复现
  8. Mysql查漏补缺笔记
  9. 程序员都很老实?你错了,其实程序员真实的样子是这样的
  10. (转) RabbitMQ学习之spring整合发送异步消息
  11. Ubuntu 14.04 网卡网关配置修改
  12. 蓝屏蓝屏代码查询器_蓝屏点播?
  13. 熬了多少个夜晚,大家期待的《网络工程师思科华为华三实战案例红宝书》即网工必备技术命令大全版本1完书...
  14. 【有限元分析】圣维南原理
  15. word插入图片被文字挡住
  16. 微信小程序如何获取高清用户头像
  17. QMS-云质-质量管理-海克斯康为什么不断收购质量管理软件(QMS)?
  18. LTE-5G学习笔记33--通信行业考哪些证可以升职加薪
  19. C++11右值引用、移动语义、完美转发详解
  20. PS高效处理图片总结

热门文章

  1. SQL:查询表中各类点数量以及各类点满足某条件数量
  2. HTML:表格、表单和rem
  3. Java中操作SFTP服务器上的文件下载上传
  4. 高效的CSV文本处理利器——univocity-parsers
  5. 图像语义分割(6)-RefineNet:用于高分辨率图像语义分割的带有恒等映射的多路精细网络
  6. 分布式存储系统学习笔记(一)—什么是分布式系统(3)—复制
  7. 正确理解TensorFlow中的logits
  8. 关于mac突然无法链接Wi-Fi的问题
  9. 基于深度学习的2D和3D仿射变换配准
  10. 介绍一篇路端传感器的cooperative perception(3D目标检测)论文