ViewPage事件冲突处理
2016-06-21 17:03
417 查看
转载:http://blog.csdn.net/lmj623565791/article/details/39480503
public class zoomImageView extends ImageView implements ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener,ViewTreeObserver.OnGlobalLayoutListener{ private static final float SCALE_MAX = 4.0f,SCALE_MID = 2.0f; //初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0; private float initScale = 1.0f; //用于存放矩阵的9个值 private final float[] matrixValues = new float[9]; private boolean once = true; //缩放的手势检测 private ScaleGestureDetector mScaleGestureDetector = null; private final Matrix mScaleMatrix = new Matrix(); //用于双击检测 private GestureDetector mGestureDetector; int lastPointerCount,mTouchSlop; boolean isCanDrag,isAutoScale,isCheckTopAndBottom = true,isChekLeftAndRight = true; float mLastX,mLastY; public zoomImageView(Context context) { this(context,null); } public zoomImageView(Context context, AttributeSet attrs) { super(context, attrs); super.setScaleType(ScaleType.MATRIX); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mScaleGestureDetector = new ScaleGestureDetector(context, this); mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onDoubleTap(MotionEvent e) { if(isAutoScale == true){ return true; } float x = e.getX(); float y = e.getY(); if(getScale() <SCALE_MID){ zoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MID,x,y),16); isAutoScale = true; }else if(getScale() >= SCALE_MID && getScale()<SCALE_MAX){ zoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MAX,x,y),16); isAutoScale = true; }else{ zoomImageView.this.postDelayed(new AutoScaleRunnable(initScale,x,y),16); isAutoScale = true; } return true; } }); this.setOnTouchListener(this); } @Override public void onGlobalLayout() { if(once){ Drawable d = getDrawable(); if(d == null){ return; } int width =getWidth(); int height = getHeight(); //拿到图片的宽和高 int dw = d.getIntrinsicWidth(); int dh = d.getIntrinsicHeight(); float scale = 1.0f; //如果图片的宽和高大于屏幕,则缩放至屏幕的宽或高 if(dw > width && dh <= height){ scale = width*1.0f/dw; } if(dh>height && dw <=width){ scale = height*1.0f/dh; } //如果高度和宽度都大于屏幕,则让其按比例适应屏幕大小 if(dw > width && dh > height){ scale = Math.min(dw * 1.0f / width, dh * 1.0f / height); } initScale = scale; //图片移到屏幕中心 mScaleMatrix.postTranslate((width - dw)/2,(height - dh)/2); mScaleMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2); setImageMatrix(mScaleMatrix); once = false; } } @Override public boolean onScale(ScaleGestureDetector detector) { float scale = getScale(); float scaleFactor = detector.getScaleFactor(); if (getDrawable() == null){ return true; } //缩放范围控制 if((scale < SCALE_MAX && scaleFactor > 1.0f) || (scale>initScale && scaleFactor<1.0f)){ //最大最小值判断 if(scaleFactor*scale <initScale){ scaleFactor = initScale/scale; } if(scaleFactor*scale > SCALE_MAX){ scaleFactor = SCALE_MAX / scale; } //设置缩放比例 // mScaleMatrix.postScale(scaleFactor, scaleFactor, getWidth() / 2, getHeight() / 2); mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(),detector.getFocusY()); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); } return true; } /** * 在缩放时,进行图片显示范围的控制 */ private void checkBorderAndCenterWhenScale() { RectF rectF = getMatrixRectF(); float deltaX= 0,deltaY = 0; int width = getWidth(); int height = getHeight(); //如果宽或高大于屏幕,则控制范围 if(rectF.width() >= width){ if(rectF.left>0){ deltaX = -rectF.left; } if (rectF.right<width){ deltaX =width - rectF.right; } } if(rectF.height()>=height){ if (rectF.top >0){ deltaY = -rectF.top; } if(rectF.bottom < height){ deltaY = height - rectF.bottom; } } //如果宽度或高度小于屏幕,则居中、 if (rectF.width()<width){ deltaX = width*0.5f - rectF.right + 0.5f*rectF.width(); } if(rectF.height()<height){ deltaY = height*0.5f - rectF.bottom + 0.5f*rectF.height(); } mScaleMatrix.postTranslate(deltaX, deltaY); } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } @Override public boolean onTouch(View v, MotionEvent event) { mScaleGestureDetector.onTouchEvent(event); float x = 0,y = 0; //拿到触摸点的个数 final int pointerCounter = event.getPointerCount(); //得到多个触摸点的x与y均值 for (int i = 0; i < pointerCounter; i++) { x+=event.getX(i); y+=event.getY(i); } x= x/pointerCounter; y = y/pointerCounter; //每当触摸点发生变化时,重置mLasX,mLastY if(pointerCounter!= lastPointerCount){ isCanDrag = false; mLastX = x; mLastY =y; } lastPointerCount = pointerCounter; RectF rectF = getMatrixRectF(); switch (event.getAction()){ case MotionEvent.ACTION_MOVE: if(rectF.width() > getWidth() || rectF.height() > getHeight()){ getParent().requestDisallowInterceptTouchEvent(true); } float dx = x - mLastX; float dy = y - mLastY; if(!isCanDrag){ isCanDrag = isCanDrag(dx,dy); } if(isCanDrag){ if(getDrawable() != null){ if(getMatrixRectF().left == 0 && dx > 0 ){ getParent().requestDisallowInterceptTouchEvent(true); } if(getMatrixRectF().right == getWidth() && dx < 0){ getParent().requestDisallowInterceptTouchEvent(true); } isCheckTopAndBottom = isChekLeftAndRight = true; //如果宽度小于屏幕宽度,则禁止左右移动 if(rectF.width() < getWidth()){ dx = 0; isChekLeftAndRight = false; } //如果高度小于屏幕高度,则禁止上下移动 if(rectF.right < getHeight()){ dy = 0; isCheckTopAndBottom = false; } mScaleMatrix.postTranslate(dx, dy); checkMatrixBounds(); setImageMatrix(mScaleMatrix); } } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: lastPointerCount = 0; break; case MotionEvent.ACTION_DOWN: if(rectF.width() > getWidth() || rectF.height() > getHeight()){ getParent().requestDisallowInterceptTouchEvent(true); } break; } if (mGestureDetector.onTouchEvent(event)){ return true; } return true; } /** * 移动时,进行边界判断,主要判断宽或高大于屏幕的 */ private void checkMatrixBounds() { RectF rectF = getMatrixRectF(); float deltaX = 0,deltaY = 0; final float viewWidth = getWidth(); final float viewHeight = getHeight(); //判断移动或者缩放后,图片显示是否超出屏幕边界 if(rectF.top > 0 && isCheckTopAndBottom){ deltaY = -rectF.top; } if (rectF.bottom <viewHeight && isCheckTopAndBottom){ deltaY = viewHeight - rectF.bottom; } if(rectF.left > 0 && isChekLeftAndRight){ deltaX = -rectF.left; } if (rectF.right <viewWidth && isChekLeftAndRight){ deltaX = viewWidth - rectF.right; } mScaleMatrix.postTranslate(deltaX, deltaY); } //是否推动行为 private boolean isCanDrag(float dx,float dy){ return Math.sqrt((dx*dx) + (dy*dy)) >= mTouchSlop; } /** * 获得当前的缩放比例 * @return */ public float getScale() { mScaleMatrix.getValues(matrixValues); return matrixValues[Matrix.MSCALE_X]; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnGlobalLayoutListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeGlobalOnLayoutListener(this); } /** * 根据当前图片的Matrix获取图片的范围 * @return */ public RectF getMatrixRectF() { Matrix matrix = mScaleMatrix; RectF rectF = new RectF(); Drawable d = getDrawable(); if(d != null){ rectF.set(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight()); matrix.mapRect(rectF); } return rectF; } class AutoScaleRunnable implements Runnable{ static final float BIGGER = 1.07f; static final float SMALLER = 0.93f; private float mTargetScale; private float tmpScale; /** * 缩放的中心 */ private float x; private float y; /** * 传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小 * * @param targetScale */ public AutoScaleRunnable(float targetScale, float x, float y) { this.mTargetScale = targetScale; this.x = x; this.y = y; if (getScale() < mTargetScale) { tmpScale = BIGGER; } else { tmpScale = SMALLER; } } @Override public void run() { // 进行缩放 mScaleMatrix.postScale(tmpScale, tmpScale, x, y); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); final float currentScale = getScale(); //如果值在合法范围内,继续缩放 if (((tmpScale > 1f) && (currentScale < mTargetScale)) || ((tmpScale < 1f) && (mTargetScale < currentScale))) { zoomImageView.this.postDelayed(this, 16); } else//设置为目标的缩放比例 { final float deltaScale = mTargetScale / currentScale; mScaleMatrix.postScale(deltaScale, deltaScale, x, y); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); isAutoScale = false; } } } }
布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administrator.testapplication.Main2Activity"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" ></android.support.v4.view.ViewPager> </RelativeLayout>
Activity中
public class Main2Activity extends Activity { private ViewPager mViewpage; private int[] mImgs = new int[]{R.mipmap.a,R.mipmap.b, R.mipmap.c}; private ImageView[] mImageViews = new ImageView[mImgs.length]; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main2); mViewpage = (ViewPager) findViewById(R.id.viewpager); mViewpage.setAdapter(new PagerAdapter() { @Override public int getCount() { return mImgs.length; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public Object instantiateItem(ViewGroup container, int position) { zoomImageView imageView = new zoomImageView(getApplicationContext()); imageView.setImageResource(mImgs[position]); container.addView(imageView); mImageViews[position] = imageView; return imageView; } }); } }
相关文章推荐
- 求二叉树中两个节点最远的距离
- bss、data和rodata区别与联系
- TCP协议中的三次握手四次挥手问题
- Asp.net中防止用户多次登录的方法
- 第三次冲刺--软件工程
- Hi-Fi
- 线程池
- iOS申请邓白氏总结
- c写Python扩展模块
- view基础知识介绍(一)
- C#取得站点跟目录
- android之对话、单复框的使用
- 关于循环的一个有趣的事情是!
- 【ICU】【2.3】如何在2.3中编译ICU资源
- 深入解析Python中的__builtins__内建对象
- Crash 解决(2)
- Dagger2 小结
- Linux常用命令汇总-cut
- 刨根问底:什么是yum源,yum的工作原理又是什么
- 《Spring实战》学习笔记-第七章:Spring MVC进阶