图片双击放大,可以移动!
2016-06-21 16:39
363 查看
转载: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: float dx = x - mLastX; float dy = y - mLastY; if(!isCanDrag){ isCanDrag = isCanDrag(dx,dy); } if(isCanDrag){ if(getDrawable() != null){ 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; } 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; } } } }
相关文章推荐
- 标准C++中的string类的用法总结
- 在调用popen时报错popen:: Cannot allocate memory
- apk动态加载机制(一): 框架的实现
- 安卓使用SOAP调用WebService
- 算法竞赛入门经典(第2版)习题1-7详解
- 【AI教程 – 初级】用钢笔工具绘制矢量铅笔图标
- android布局中include的使用
- Android
- NVR利用onvif协议去申请摄像机的码流时,申请不到子码流
- mysql concat_ws与concat区别
- 查看Sql语句执行速度
- 记住密码"功能的正确设计
- json解析精度问题
- 禁止使用test类的就是禁止使用本来的$this对象.可以调用父类的对象
- intellij打开工程在每个java文件上有个红色的无效符的解决办法
- RecyclerView的五个开源项目
- Linux常用命令汇总-head
- linux系统之上搭建maven 之nexus服务篇
- Happy Number(C++)
- IEnumerable,ICollection,IList,List之间的区别