
androID VIEwPager是一个经常要用到的组件,但androID系统本身为我们提供的VIEwPager是没有任何效果的,只能是一页一页的滑动,这样会让人感觉很死板,在看一些知名大公司的App时,看到了他们的VIEwPager在滑动到最开始或者最后的时候是有一个d性效果的,使用起来感觉非常的好,于是乎就是百度搜了一下,在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() { @OverrIDe public voID onAnimationStart(Animator animation) { } @OverrIDe public voID onAnimationRepeat(Animator animation) { } @OverrIDe public voID onAnimationEnd(Animator animation) { startAnimation(0); } @OverrIDe public 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; } @OverrIDe public 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 { @OverrIDe public voID onPageScrolled(int position,float positionOffset,int positionOffsetPixels) { if (mScrollListener != null) { mScrollListener.onPageScrolled(position,positionOffset,positionOffsetPixels); } mScrollposition = position; mScrollpositionOffset = positionOffset; mLastposition = position; invalIDateVisibleChilds(position); } @OverrIDe public voID onPageSelected(int position) { if (mScrollListener != null) { mScrollListener.onPageSelected(position); } } @OverrIDe public voID onPageScrollStateChanged(final int state) { if (mScrollListener != null) { mScrollListener.onPageScrollStateChanged(state); } if (state == SCRolL_STATE_IDLE) { mScrollpositionOffset = 0; } } } @OverrIDe public 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; } } @OverrIDe public boolean dispatchtouchEvent(MotionEvent ev) { try { return super.dispatchtouchEvent(ev); } catch (IllegalArgumentException e) { e.printstacktrace(); return false; } catch (Arrayindexoutofboundsexception e) { e.printstacktrace(); return false; } } @OverrIDe public 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 event final 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); } } @OverrIDe protected 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().@R_403_5990@(); final float translateX = (float) mOverscrollTranslation * (mOverscrollEffect.mOverscroll > 0 ? Math.min(mOverscrollEffect.mOverscroll,1) : Math.max( mOverscrollEffect.mOverscroll,-1)); mCamera.save(); mCamera.translate(-translateX,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水平滑动d性效果全部内容,希望文章能够帮你解决android自定义ViewPager水平滑动d性效果所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)