`

ViewPager的弹性缩回效果

阅读更多
         android 实现划屏效果控件有:ViewFlipper,用过的同学们都知道,这个控件有点死板,只能等待你手势执行完毕后才执行滑动效果,用起来很不爽,不过ViewPager可以很容易实现这个效果.但是有个缺陷,也就是在首页时候向左拽,在最后一页向右拽,这两者是没有效果的,而iphone的效果是你拖拽出现一片空的page会自动缩回首页或尾页,这个看起来很爽,不过android强大之处你可以自己实现,我是菜鸟,说的都是个人观点,获取有很多很多的bug吧,若有不足之处请您多多指出,我将感激不尽.
       首先要实现ViewPager效果,必须要导入一个jar包“android-support-v4.jar”这个jar包可以在android sdk中找到路径为”E:\android-sdk-windows\extras\android\support\v4“
          关于细节上的问题,自己可以网上搜搜.在这里我要讲两点”怎么实现禁止滑向下一页“
          其实实现方法很简单,一说你也就知道了.”多创建两个屏,用于放在第一屏和最后一屏“嘿嘿,知道了吧,我其实也没做什么,就是稍微修改了一下,具体代码如下:
        主要是这个回调 OnPageChangeListener接口,当页数改变回调用,也就是当你左右滑动的时候会执行,还有一个重要的方法:pager.setCurrentItem(arg0 - 1);你要显示哪一页的时候也会调用调用.

源码已经优化:
package com.jj.viewpager;

import java.util.ArrayList;

import android.app.ActivityGroup;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends ActivityGroup {
	private ViewPager pager;
	private ArrayList<View> pageViews=new ArrayList<View>();
	private LinearLayout layout;
	private int curPosition=1;//当前显示页,从1开始
	private ArrayList<ImageView> imageViews;
	private int points;//多少个点
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		initViews();
	}
	
	void initViews() {
		View view00 = getLocalActivityManager().startActivity("activity00",
				new Intent(this, NullActivity.class)).getDecorView();
		View view01 = getLocalActivityManager().startActivity("activity01",
				new Intent(this, MainActivity1.class)).getDecorView();
		View view02 = getLocalActivityManager().startActivity("activity02",
				new Intent(this, MainActivity2.class)).getDecorView();
		View view03 = getLocalActivityManager().startActivity("activity03",
				new Intent(this, MainActivity3.class)).getDecorView();
		View view04 = getLocalActivityManager().startActivity("activity00",
				new Intent(this, NullActivity.class)).getDecorView();
		pageViews.add(view00);
		pageViews.add(view01);
		pageViews.add(view02);
		pageViews.add(view03);
		pageViews.add(view04);
		
		pager = (ViewPager) findViewById(R.id.vp_contains);
		pager.setAdapter(new PagerViewAdapter());
		pager.setCurrentItem(curPosition);
		pager.setOnPageChangeListener(new OnPageChangeListener() {

			@Override
			public void onPageSelected(int position) {
				if (position == 0) {
					pager.setCurrentItem(position + 1);
				} else if(position == pageViews.size() - 1){
					pager.setCurrentItem(position - 1);
				}
				updateViews(pager.getCurrentItem());

			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {

			}

			@Override
			public void onPageScrollStateChanged(int arg0) {

			}
		});
		
		imageViews = new ArrayList<ImageView>();
		layout = (LinearLayout) findViewById(R.id.layout);	
		points=pageViews.size()-2;
		for (int i = 0; i < points; i++) {
			ImageView imageView = new ImageView(this);
			imageView.setLayoutParams(new LayoutParams(5, 5));
			
			LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
					new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
			params.leftMargin = 20;
			params.rightMargin = 20;
			layout.addView(imageView, params);
			imageViews.add(imageView);

			imageView.setBackgroundResource(i == pager.getCurrentItem()-1?R.drawable.d2:R.drawable.d1);
		}
	}

	public void updateViews(int index) {
		for (int i = 0; i < points; i++) {
			imageViews.get(i).setBackgroundResource(i==index-1?R.drawable.d2:R.drawable.d1);
		}
	}

	class PagerViewAdapter extends PagerAdapter {
		@Override
		public int getCount() {
			return pageViews.size();
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0 == arg1;
		}

		@Override
		public int getItemPosition(Object object) {
			// TODO Auto-generated method stub
			return super.getItemPosition(object);
		}

		@Override
		public void destroyItem(View arg0, int arg1, Object arg2) {
			// TODO Auto-generated method stub
			((ViewPager) arg0).removeView(pageViews.get(arg1));
		}

		@Override
		public Object instantiateItem(View arg0, int arg1) {
			((ViewPager) arg0).addView(pageViews.get(arg1));
			return pageViews.get(arg1);
		}

	}
}


完整的看附件。

简单方法实现ViewPage 循环滚动

ViewPager之——水平滑动弹性效果
http://stackoverflow.com/questions/13759862/android-viewpager-how-to-achieve-the-bound-effect

上面的方式不靠谱,还是用这个吧,好东西总是在最后。
public class BounceBackViewPager extends ViewPager {

/**
 * maximum z distance to translate child view
 */
final static int DEFAULT_OVERSCROLL_TRANSLATION = 150;

/**
 * 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, DEFAULT_OVERSCROLL_TRANSLATION);
    mOverscrollAnimationDuration = a.getInt(R.styleable.BounceBackViewPager_overscroll_animation_duration, 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().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;
}
}

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BounceBackViewPager">
    <!--
    determines the maximum amount of translation along the z-axis during the overscroll. 
    Default is 150.
    -->
    <attr name="overscroll_translation" format="dimension" />

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



子ViewPager滑到边缘后直接滑动父ViewPager
http://blog.csdn.net/lcq5211314123/article/details/41248569

ViewPager之——3D效果应用
http://blog.csdn.net/lcq5211314123/article/details/41120315


Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI
http://blog.csdn.net/lmj623565791/article/details/42160391

打造史上最容易使用的Tab指示符——Indicator
http://blog.csdn.net/qibin0506/article/details/42046559

一个ViewPager的库,支持水平翻页,上下翻页,无限翻页
http://www.jcodecraeer.com/a/opensource/2015/0207/2430.html


MultiViewPager 是根据support-v4 中ViewPager 控件改造而来,它可以让ViewPager一次显示更宽或者更窄的内容,它很好的处理了page之间的位置关系,能保证每次被选中的page显示在中间。
http://www.jcodecraeer.com/a/opensource/2015/0207/2432.html
分享到:
评论
1 楼 lxh2002 2013-04-26  
试了一下,效果确实不错,感谢!

相关推荐

Global site tag (gtag.js) - Google Analytics