android viewpager显示三个item(横屏使用)-笔记

来源:互联网 发布:网络棋牌游戏靠谱吗 编辑:程序博客网 时间:2024/06/07 10:54

简单做个笔记,效果如下:



实现2步:

1.在继承PagerAdapter里重写收下方法:

@Overridepublic float getPageWidth(int position) {return (float) 0.33;}


2.设置动画:

mViewPager.setPageTransformer(true, new ViewPager.PageTransformer() {@Overridepublic void transformPage(View page, float position) {float v = Math.abs(position - 0.33f);float v1 = (float) (2 * (v * v));page.setScaleY(1 - v1);page.setScaleX(1 - v1);}});
注1:0.33是屏幕的三分之一,float v1 = (float) (2 * (v * v));是计算而已,详见可见这

注2:效果图中前后都加了一个空白的item,每个item也设置了padding值。


给上全的Adapter:

public class ContractVpHAdapter extends PagerAdapter {private List<String> mDataList;private List<DragImageView> mViewList;private Context mContext;private DisplayImageOptions mOptions;private ImgViewPager mImgViewPager;public ContractVpHAdapter(Context c, List<String> data, ImgViewPager imgViewPager) {mContext = c;mDataList = data;mImgViewPager = imgViewPager;mViewList = new ArrayList<DragImageView>();notifyDataView();mOptions = new DisplayImageOptions.Builder()// .showImageOnLoading(R.drawable.icon_apk)//// .showImageOnFail(R.drawable.icon_apk)//.cacheInMemory(true)//.cacheOnDisk(true)//.bitmapConfig(Bitmap.Config.RGB_565)//.build();mImgViewPager.addOnPageChangeListener(new SimpleOnPageChangeListener() {@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);for (int i = 0; i < mViewList.size(); i++) {if (null != mViewList.get(i)) {mViewList.get(i).setCanDrag(false);}}if ((position + 1) < mViewList.size()) {mViewList.get(position + 1).setCanDrag(true);}}});}@Overridepublic float getPageWidth(int position) {return (float) 0.33;}@Overridepublic int getCount() {return mViewList.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}@Overridepublic int getItemPosition(Object object) {return super.getItemPosition(object);}@Overridepublic void destroyItem(ViewGroup arg0, int arg1, Object arg2) {((ViewPager) arg0).removeView(mViewList.get(arg1));}@Overridepublic View instantiateItem(ViewGroup arg0, int arg1) {((ViewPager) arg0).addView(mViewList.get(arg1));return mViewList.get(arg1);}public void notifyDataView() {mViewList.clear();if (mDataList.isEmpty()) {notifyDataSetChanged();return;}mViewList.add(getImg());for (int i = 0; i < mDataList.size(); i++) {getView(i);}mViewList.add(getImg());notifyDataSetChanged();}private void getView(int i) {DragImageView imageView = getImg();ImageLoader.getInstance().displayImage(mDataList.get(i), imageView, mOptions);mViewList.add(imageView);if (i == 1) {imageView.setCanDrag(true);}}private DragImageView getImg() {DragImageView imageView = new DragImageView(mContext);imageView.setOnMovingListener(mImgViewPager);imageView.setCanDrag(false);imageView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));imageView.setPadding(Tool.dip2px(mContext, 12), 0, Tool.dip2px(mContext, 12), 0);return imageView;}}



上面有二个自定义类DragImageView、ImgViewPager,为了实现可以直接在Item里直接拖动,放大。

DragImageView:

/** * @ClassName: DragImageView * @Description: 带放大、缩小、移动效果的ImageView *  */public class DragImageView extends ImageView {/** * 初始化状态常量 */public static final int STATUS_INIT = 0;/** 拖拉照片模式 */private static final int MODE_DRAG = 1;/** 放大缩小照片模式 */private static final int MODE_ZOOM = 2;/** 不支持Matrix */private static final int MODE_UNABLE = 3;private int mMode = 0;//public final static String TAG = "MatrixImageView";private GestureDetector mGestureDetector;/** 模板Matrix,用以初始化 */private Matrix mMatrix = new Matrix();/** 图片长度 */private float mImageWidth;/** 图片高度 */private float mImageHeight;/** 原始缩放级别 */private float mScale;private OnMovingListener moveListener;private OnSingleTapListener singleTapListener;/** 原始X轴位置 */private float initX;/** 原始Y轴位置 */private float initY;/** * 记录当前图片的宽度,图片被缩放时,这个值会一起变动 */private float currentBitmapWidth;/** * 记录当前图片的高度,图片被缩放时,这个值会一起变动 */private float currentBitmapHeight;private boolean isCanDrag = true;public DragImageView(Context context, AttributeSet attrs) {super(context, attrs);MatrixTouchListener mListener = new MatrixTouchListener();setOnTouchListener(mListener);mGestureDetector = new GestureDetector(getContext(), new GestureListener(mListener));// 背景设置为balck//setBackgroundColor(Color.WHITE);// 将缩放类型设置为CENTER_INSIDE,表示把图片居中显示,并且宽高最大值为控件宽高setScaleType(ScaleType.FIT_CENTER);}public DragImageView(Context context) {super(context, null);MatrixTouchListener mListener = new MatrixTouchListener();setOnTouchListener(mListener);mGestureDetector = new GestureDetector(getContext(), new GestureListener(mListener));// 背景设置为balck// setBackgroundColor(Color.WHITE);// 将缩放类型设置为CENTER_INSIDE,表示把图片居中显示,并且宽高最大值为控件宽高setScaleType(ScaleType.FIT_CENTER);}public boolean isCanDrag() {return isCanDrag;}public void setCanDrag(boolean isCanDrag) {this.isCanDrag = isCanDrag;}public void setOnMovingListener(OnMovingListener listener) {moveListener = listener;}public void setOnSingleTapListener(OnSingleTapListener onSingleTapListener) {this.singleTapListener = onSingleTapListener;}@Overridepublic void setImageBitmap(Bitmap bm) {// TODO Auto-generated method stubsuper.setImageBitmap(bm);// 大小为0 表示当前控件大小未测量 设置监听函数 在绘制前赋值if (getWidth() == 0) {ViewTreeObserver vto = getViewTreeObserver();vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {public boolean onPreDraw() {initData();// 赋值结束后,移除该监听函数DragImageView.this.getViewTreeObserver().removeOnPreDrawListener(this);return true;}});} else {initData();}}/** * 初始化模板Matrix和图片的其他数据 */private void initData() {// 设置完图片后,获取该图片的坐标变换矩阵mMatrix.set(getImageMatrix());float[] values = new float[9];mMatrix.getValues(values);// 图片宽度为屏幕宽度除缩放倍数// 要考虑长图,去掉了两边的空白mImageWidth = (getWidth() - values[Matrix.MTRANS_X] * 2) / values[Matrix.MSCALE_X];mImageHeight = (getHeight() - values[Matrix.MTRANS_Y] * 2) / values[Matrix.MSCALE_Y];mScale = values[Matrix.MSCALE_X];initX = values[Matrix.MTRANS_X];initY = values[Matrix.MTRANS_Y];currentBitmapWidth = mImageWidth * values[Matrix.MSCALE_X];currentBitmapHeight = mImageHeight * values[Matrix.MSCALE_Y];}public class MatrixTouchListener implements OnTouchListener {/** 最大缩放级别 */float mMaxScale = 4f;// 最小缩放// float minScale = 1f;/** 双击时的缩放级别 */float mDobleClickScale = 2f;private int mMode = 0;///** 缩放开始时的手指间距 */private float mStartDis;/** 当前Matrix */private Matrix mCurrentMatrix = new Matrix();/** 用于记录开始时候的坐标位置 *//** 和ViewPager交互相关,判断当前是否可以左移、右移 */boolean mLeftDragable;boolean mRightDragable;/** 是否第一次移动 */boolean mFirstMove = false;/** * 记录图片在矩阵上的横向偏移值 */private float totalTranslateX;/** * 记录图片在矩阵上的纵向偏移值 */private float totalTranslateY;private PointF mStartPoint = new PointF();@Overridepublic boolean onTouch(View v, MotionEvent event) {if (!isCanDrag) {return true;}switch (event.getActionMasked()) {case MotionEvent.ACTION_DOWN:// 设置拖动模式mMode = MODE_DRAG;mStartPoint.set(event.getX(), event.getY());isMatrixEnable();startDrag();checkDragable();break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:reSetMatrix();stopDrag();break;case MotionEvent.ACTION_MOVE:if (mMode == MODE_ZOOM) {setZoomMatrix(event);} else if (mMode == MODE_DRAG) {setDragMatrix(event);} else {stopDrag();}break;case MotionEvent.ACTION_POINTER_DOWN:if (mMode == MODE_UNABLE)return true;mMode = MODE_ZOOM;mStartDis = distance(event);break;case MotionEvent.ACTION_POINTER_UP:break;default:break;}return mGestureDetector.onTouchEvent(event);}/** * 子控件开始进入移动状态,令ViewPager无法拦截对子控件的Touch事件 */private void startDrag() {if (moveListener != null)moveListener.startDrag();}/** * 子控件开始停止移动状态,ViewPager将拦截对子控件的Touch事件 */private void stopDrag() {if (moveListener != null)moveListener.stopDrag();}/** * 根据当前图片左右边缘设置可拖拽状态 */private void checkDragable() {mLeftDragable = true;mRightDragable = true;mFirstMove = true;float[] values = new float[9];getImageMatrix().getValues(values);// 图片左边缘离开左边界,表示不可右移if (values[Matrix.MTRANS_X] >= 0)mRightDragable = false;// 图片右边缘离开右边界,表示不可左移Log.d("mImageWidth*values[Matrix.MSCALE_X]",mImageWidth + ":" + values[Matrix.MSCALE_X] + ":" + values[Matrix.MTRANS_X] + ":" + getWidth());if ((mImageWidth) * values[Matrix.MSCALE_X] < getWidth()) {mLeftDragable = false;mRightDragable = false;}if ((mImageWidth) * values[Matrix.MSCALE_X] + values[Matrix.MTRANS_X] <= getWidth()) {mLeftDragable = false;}}/** * 设置拖拽状态下的Matrix *  * @param event */public void setDragMatrix(MotionEvent event) {if (isZoomChanged()) {float dx = event.getX() - mStartPoint.x; // 得到x轴的移动距离float dy = event.getY() - mStartPoint.y; // 得到x轴的移动距离// 避免和双击冲突,大于10f才算是拖动if (Math.sqrt(dx * dx + dy * dy) > 10f) {mStartPoint.set(event.getX(), event.getY());// 在当前基础上移动mCurrentMatrix.set(getImageMatrix());float[] values = new float[9];mCurrentMatrix.getValues(values);dy = checkDyBound(values, dy);dx = checkDxBound(values, dx, dy);mCurrentMatrix.postTranslate(dx, dy);// mCurrentMatrix.postTranslate(getWidth()/2,// getHeight()/2);setImageMatrix(mCurrentMatrix);}} else {stopDrag();}}/** * 判断缩放级别是否是改变过 *  * @return true表示非初始值,false表示初始值 */private boolean isZoomChanged() {float[] values = new float[9];getImageMatrix().getValues(values);// 获取当前X轴缩放级别float scale = values[Matrix.MSCALE_X];// 获取模板的X轴缩放级别,两者做比较return scale != mScale;}/** * 和当前矩阵对比,检验dy,使图像移动后不会超出ImageView边界 *  * @param values * @param dy * @return */private float checkDyBound(float[] values, float dy) {float height = getHeight();if (mImageHeight * values[Matrix.MSCALE_Y] < height)return 0;if (values[Matrix.MTRANS_Y] + dy > 0)dy = -values[Matrix.MTRANS_Y];else if (values[Matrix.MTRANS_Y] + dy < -(mImageHeight * values[Matrix.MSCALE_Y] - height))dy = -(mImageHeight * values[Matrix.MSCALE_Y] - height) - values[Matrix.MTRANS_Y];return dy;}/** * 和当前矩阵对比,检验dx,使图像移动后不会超出ImageView边界 *  * @param values * @param dx * @return */private float checkDxBound(float[] values, float dx, float dy) {float width = getWidth();if (!mLeftDragable && dx < 0) {// 加入和y轴的对比,表示在监听到垂直方向的手势时不切换Itemif (Math.abs(dx) * 0.4f > Math.abs(dy) && mFirstMove) {stopDrag();}return 0;}if (!mRightDragable && dx > 0) {// 加入和y轴的对比,表示在监听到垂直方向的手势时不切换Itemif (Math.abs(dx) * 0.4f > Math.abs(dy) && mFirstMove) {stopDrag();}return 0;}mLeftDragable = true;mRightDragable = true;if (mFirstMove)mFirstMove = false;if (mImageWidth * values[Matrix.MSCALE_X] < width) {return 0;}if (values[Matrix.MTRANS_X] + dx > 0) {dx = -values[Matrix.MTRANS_X];} else if (values[Matrix.MTRANS_X] + dx < -(mImageWidth * values[Matrix.MSCALE_X] - width)) {dx = -(mImageWidth * values[Matrix.MSCALE_X] - width) - values[Matrix.MTRANS_X];}return dx;}/** * 设置缩放Matrix *  * @param event */private void setZoomMatrix(MotionEvent event) {// 只有同时触屏两个点的时候才执行if (event.getPointerCount() < 2)return;float endDis = distance(event);// 结束距离if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10float scale = endDis / mStartDis;// 得到缩放倍数mCurrentMatrix.set(getImageMatrix());// 初始化Matrixfloat[] values = new float[9];mCurrentMatrix.getValues(values);scale = checkMaxScale(scale, values);Log.d("缩放倍数", scale + "");// PointF centerF=getCenter(scale,values);// mCurrentMatrix.postScale(scale, scale,centerF.x,centerF.y);// setImageMatrix(mCurrentMatrix);// checkRest();float scaledWidth = mImageWidth * values[Matrix.MSCALE_X] * scale;float scaledHeight = mImageHeight * values[Matrix.MSCALE_Y] * scale;totalTranslateX = values[Matrix.MTRANS_X];totalTranslateY = values[Matrix.MTRANS_Y];// testfloat translateX = 0f;float translateY = 0f;float xPoint0 = event.getX(0);float yPoint0 = event.getY(0);float xPoint1 = event.getX(1);float yPoint1 = event.getY(1);float centerPointX = (xPoint0 + xPoint1) / 2;float centerPointY = (yPoint0 + yPoint1) / 2;if (currentBitmapWidth < getWidth()) {translateX = (getWidth() - scaledWidth) / 2f;} else {translateX = totalTranslateX * scale + centerPointX * (1 - scale);// 进行边界检查,保证图片缩放后在水平方向上不会偏移出屏幕if (translateX > 0) {translateX = 0;} else if (getWidth() - translateX > scaledWidth) {translateX = getWidth() - scaledWidth;}}// 如果当前图片高度小于屏幕高度,则按屏幕中心的纵坐标进行垂直缩放。否则按两指的中心点的纵坐标进行垂直缩放if (currentBitmapHeight < getHeight()) {translateY = (getHeight() - scaledHeight) / 2f;} else {translateY = totalTranslateY * scale + centerPointY * (1 - scale);// 进行边界检查,保证图片缩放后在垂直方向上不会偏移出屏幕if (translateY > 0) {translateY = 0;} else if (getHeight() - translateY > scaledHeight) {translateY = getHeight() - scaledHeight;}}// 缩放后对图片进行偏移,以保证缩放后中心点位置不变Matrix matrix = new Matrix();matrix.reset();matrix.postScale(values[Matrix.MSCALE_X] * scale, values[Matrix.MSCALE_Y] * scale);matrix.postTranslate(translateX, translateY);// mCurrentMatrix.preTranslate(translateX, translateY);// mCurrentMatrix.postScale(scale,scale);// totalTranslateX = translateX;// totalTranslateY = translateY;currentBitmapWidth = scaledWidth;currentBitmapHeight = scaledHeight;setImageMatrix(matrix);checkRest();mStartDis = endDis;// 重置距离}}/** * 获取缩放的中心点。 *  * @param scale * @param values * @return */private PointF getCenter(float scale, float[] values) {// 缩放级别小于原始缩放级别时或者为放大状态时,返回ImageView中心点作为缩放中心点if (scale * values[Matrix.MSCALE_X] < mScale || scale >= 1) {return new PointF(getWidth() / 2, getHeight() / 2);}if (mImageWidth * values[Matrix.MSCALE_X] * scale <= getWidth()) {return new PointF(getWidth() / 2, getHeight() / 2);}float cx = getWidth() / 2;float cy = getHeight() / 2;// 以ImageView中心点为缩放中心,判断缩放后的图片左边缘是否会离开ImageView左边缘,是的话以左边缘为X轴中心if ((getWidth() / 2 - values[Matrix.MTRANS_X]) * scale <= getWidth() / 2)cx = 0;// 判断缩放后的右边缘是否会离开ImageView右边缘,是的话以右边缘为X轴中心if ((mImageWidth * values[Matrix.MSCALE_X] + values[Matrix.MTRANS_X]) * scale <= getWidth())cx = getWidth();return new PointF(cx, cy);}/** * 检验scale,使图像缩放后不会超出最大倍数 *  * @param scale * @param values * @return */private float checkMaxScale(float scale, float[] values) {if (scale * values[Matrix.MSCALE_X] > mMaxScale * mScale) {scale = mMaxScale * mScale / values[Matrix.MSCALE_X];} else if (scale * values[Matrix.MSCALE_X] <= mScale) {scale = 1;}return scale;}/** * 重置Matrix */private void reSetMatrix() {if (checkRest()) {mCurrentMatrix.set(mMatrix);setImageMatrix(mCurrentMatrix);} else {// 判断Y轴是否需要更正float[] values = new float[9];getImageMatrix().getValues(values);float height = mImageHeight * values[Matrix.MSCALE_Y];if (height < getHeight()) {// 在图片真实高度小于容器高度时,Y轴居中,Y轴理想偏移量为两者高度差/2,float topMargin = (getHeight() - height) / 2;if (topMargin != values[Matrix.MTRANS_Y]) {mCurrentMatrix.set(getImageMatrix());mCurrentMatrix.postTranslate(0, topMargin - values[Matrix.MTRANS_Y]);setImageMatrix(mCurrentMatrix);}}}}/** * 判断是否需要重置 *  * @return 当前缩放级别小于模板缩放级别时,重置 */private boolean checkRest() {// TODO Auto-generated method stubfloat[] values = new float[9];getImageMatrix().getValues(values);// 获取当前X轴缩放级别float scale = values[Matrix.MSCALE_X];// 获取模板的X轴缩放级别,两者做比较return scale < mScale;}/** * 判断是否支持Matrix */private void isMatrixEnable() {// 当加载出错时,不可缩放if (getScaleType() != ScaleType.CENTER) {setScaleType(ScaleType.MATRIX);} else {mMode = MODE_UNABLE;// 设置为不支持手势}}/** * 计算两个手指间的距离 *  * @param event * @return */private float distance(MotionEvent event) {float dx = event.getX(1) - event.getX(0);float dy = event.getY(1) - event.getY(0);/** 使用勾股定理返回两点之间的距离 */return (float) Math.sqrt(dx * dx + dy * dy);}/** * 双击时触发 */public void onDoubleClick() {float scale = isZoomChanged() ? 1 : mDobleClickScale;mCurrentMatrix.set(mMatrix);// 初始化MatrixmCurrentMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2);setImageMatrix(mCurrentMatrix);}}public void resetZoom() {Matrix mCurrentMatrix = new Matrix();mCurrentMatrix.set(mMatrix);// 初始化MatrixmCurrentMatrix.postScale(1, 1, getWidth() / 2, getHeight() / 2);setImageMatrix(mCurrentMatrix);}private class GestureListener extends SimpleOnGestureListener {private final MatrixTouchListener listener;public GestureListener(MatrixTouchListener listener) {this.listener = listener;}@Overridepublic boolean onDown(MotionEvent e) {// 捕获Down事件return true;}@Overridepublic boolean onDoubleTap(MotionEvent e) {// 触发双击事件listener.onDoubleClick();return true;}@Overridepublic boolean onSingleTapUp(MotionEvent e) {// TODO Auto-generated method stubreturn super.onSingleTapUp(e);}@Overridepublic void onLongPress(MotionEvent e) {// TODO Auto-generated method stubsuper.onLongPress(e);}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return super.onScroll(e1, e2, distanceX, distanceY);}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return super.onFling(e1, e2, velocityX, velocityY);}@Overridepublic void onShowPress(MotionEvent e) {// TODO Auto-generated method stubsuper.onShowPress(e);}@Overridepublic boolean onDoubleTapEvent(MotionEvent e) {// TODO Auto-generated method stubreturn super.onDoubleTapEvent(e);}@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {if (singleTapListener != null)singleTapListener.onSingleTap();return super.onSingleTapConfirmed(e);}}/** * @ClassName: OnChildMovingListener * @Description: MatrixImageView移动监听接口,用以组织ViewPager对Move操作的拦截 *  */public interface OnMovingListener {public void startDrag();public void stopDrag();}/** * @ClassName: OnSingleTapListener * @Description: 监听ViewPager屏幕单击事件,本质是监听子控件MatrixImageView的单击事件 *  */public interface OnSingleTapListener {public void onSingleTap();}}


ImgViewPager:

public class ImgViewPager extends ViewPager implements OnMovingListener {public final static String TAG = "AlbumViewPager";/** 当前子控件是否处理拖动状态 */private boolean mChildIsBeingDragged = false;public ImgViewPager(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent arg0) {if (mChildIsBeingDragged)return false;return super.onInterceptTouchEvent(arg0);}@Overridepublic void startDrag() {mChildIsBeingDragged = true;}@Overridepublic void stopDrag() {mChildIsBeingDragged = false;}}



原创粉丝点击