以下是自定义支持手势缩放的zoomImageview,代码拿过去直接可以用

public class ZoomImageView extends ImageView implements OnScaleGestureListener,OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener{private static final String TAG = ZoomImageView.class.getSimpleName();public static final float SCALE_MAX = 4.0f;private static final float SCALE_MID = 2.0f;/*** 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0*/private float initScale = 1.0f;private boolean once = true;/*** 用于存放矩阵的9个值*/private final float[] matrixValues = new float[9];/*** 缩放的手势检测*/private ScaleGestureDetector mScaleGestureDetector = null;private final Matrix mScaleMatrix = new Matrix();/*** 用于双击检测*/private GestureDetector mGestureDetector;private boolean isAutoScale;private int mTouchSlop;private float mLastX;private float mLastY;private boolean isCanDrag;private int lastPointerCount;private boolean isCheckTopAndBottom = true;private boolean isCheckLeftAndRight = true;public ZoomImageView(Context context){this(context, null);}public ZoomImageView(Context context, AttributeSet attrs){super(context, attrs);super.setScaleType(ScaleType.MATRIX);mGestureDetector = new GestureDetector(context,new SimpleOnGestureListener(){@Overridepublic boolean onDoubleTap(MotionEvent e){if (isAutoScale == true)return true;float x = e.getX();float y = e.getY();Log.e("DoubleTap", getScale() + " , " + initScale);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;}});mScaleGestureDetector = new ScaleGestureDetector(context, this);this.setOnTouchListener(this);}/*** 自动缩放的任务* * @author zhy* */private 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;}}@Overridepublic 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;}}}@SuppressLint("NewApi")@Overridepublic 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,detector.getFocusX(), detector.getFocusY());checkBorderAndCenterWhenScale();setImageMatrix(mScaleMatrix);}return true;}/*** 在缩放时,进行图片显示范围的控制*/private void checkBorderAndCenterWhenScale(){RectF rect = getMatrixRectF();float deltaX = 0;float deltaY = 0;int width = getWidth();int height = getHeight();// 如果宽或高大于屏幕,则控制范围if (rect.width() >= width){if (rect.left > 0){deltaX = -rect.left;}if (rect.right < width){deltaX = width - rect.right;}}if (rect.height() >= height){if (rect.top > 0){deltaY = -rect.top;}if (rect.bottom < height){deltaY = height - rect.bottom;}}// 如果宽或高小于屏幕,则让其居中if (rect.width() < width){deltaX = width * 0.5f - rect.right + 0.5f * rect.width();}if (rect.height() < height){deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();}Log.e(TAG, "deltaX = " + deltaX + " , deltaY = " + deltaY);mScaleMatrix.postTranslate(deltaX, deltaY);}/*** 根据当前图片的Matrix获得图片的范围* * @return*/private RectF getMatrixRectF(){Matrix matrix = mScaleMatrix;RectF rect = new RectF();Drawable d = getDrawable();if (null != d){rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());matrix.mapRect(rect);}return rect;}@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector){return true;}@Overridepublic void onScaleEnd(ScaleGestureDetector detector){}@Overridepublic boolean onTouch(View v, MotionEvent event){if (mGestureDetector.onTouchEvent(event))return true;mScaleGestureDetector.onTouchEvent(event);float x = 0, y = 0;// 拿到触摸点的个数final int pointerCount = event.getPointerCount();// 得到多个触摸点的x与y均值for (int i = 0; i < pointerCount; i++){x += event.getX(i);y += event.getY(i);}x = x / pointerCount;y = y / pointerCount;/*** 每当触摸点发生变化时,重置mLasX , mLastY*/if (pointerCount != lastPointerCount){isCanDrag = false;mLastX = x;mLastY = y;}lastPointerCount = pointerCount;RectF rectF = getMatrixRectF();switch (event.getAction()){case MotionEvent.ACTION_DOWN:if (rectF.width() > getWidth() || rectF.height() > getHeight()){getParent().requestDisallowInterceptTouchEvent(true);}break;case MotionEvent.ACTION_MOVE:if (rectF.width() > getWidth() || rectF.height() > getHeight()){getParent().requestDisallowInterceptTouchEvent(true);}Log.e(TAG, "ACTION_MOVE");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(false);// }//// if (getMatrixRectF().right == getWidth() && dx < 0)// {// getParent().requestDisallowInterceptTouchEvent(false);// }isCheckLeftAndRight = isCheckTopAndBottom = true;// 如果宽度小于屏幕宽度,则禁止左右移动if (rectF.width() < getWidth()){dx = 0;isCheckLeftAndRight = false;}// 如果高度小雨屏幕高度,则禁止上下移动if (rectF.height() < 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:Log.e(TAG, "ACTION_UP");lastPointerCount = 0;break;}return true;}/*** 获得当前的缩放比例* * @return*/public final float getScale(){mScaleMatrix.getValues(matrixValues);return matrixValues[Matrix.MSCALE_X];}@Overrideprotected void onAttachedToWindow(){super.onAttachedToWindow();getViewTreeObserver().addOnGlobalLayoutListener(this);}@SuppressWarnings("deprecation")@Overrideprotected void onDetachedFromWindow(){super.onDetachedFromWindow();getViewTreeObserver().removeGlobalOnLayoutListener(this);}@Overridepublic void onGlobalLayout(){if (once){Drawable d = getDrawable();if (d == null)return;Log.e(TAG, d.getIntrinsicWidth() + " , " + d.getIntrinsicHeight());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(width * 1.0f / dw, height * 1.0f / dh);}initScale = scale;Log.e(TAG, "initScale = " + initScale);mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);mScaleMatrix.postScale(scale, scale, getWidth() / 2,getHeight() / 2);// 图片移动至屏幕中心setImageMatrix(mScaleMatrix);once = false;}}/*** 移动时,进行边界判断,主要判断宽或高大于屏幕的*/private void checkMatrixBounds(){RectF rect = getMatrixRectF();float deltaX = 0, deltaY = 0;final float viewWidth = getWidth();final float viewHeight = getHeight();// 判断移动或缩放后,图片显示是否超出屏幕边界if (rect.top > 0 && isCheckTopAndBottom){deltaY = -rect.top;}if (rect.bottom < viewHeight && isCheckTopAndBottom){deltaY = viewHeight - rect.bottom;}if (rect.left > 0 && isCheckLeftAndRight){deltaX = -rect.left;}if (rect.right < viewWidth && isCheckLeftAndRight){deltaX = viewWidth - rect.right;}mScaleMatrix.postTranslate(deltaX, deltaY);}/*** 是否是推动行为* * @param dx* @param dy* @return*/private boolean isCanDrag(float dx, float dy){return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;}}

安卓图片手势缩放-源码相关推荐

  1. 安卓图片手势缩放、旋转、移动

    两个ImageView都可以手势缩放.旋转.移动 自定义ImageView一 import android.content.Context; import android.graphics.Matri ...

  2. 安卓开发仿微信图片拖拽_Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动)...

    [实例简介] Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动) [实例截图] [核心代码] ImageDemo-2014-02-18 └── ImageDemo-2014-02-18 ├ ...

  3. 简洁的安卓软件下载页源码

    介绍: 简洁的安卓软件下载页源码 网盘下载地址: https://zijiewangpan.com/QMOkB99n2hg 图片:

  4. H5即时通讯IM聊天APP系统 带原生/安卓苹果端APP源码

    介绍: 带原生/安卓苹果端APP源码+详细视频教程 朋友互站4000+购买来的通讯,全原生,并不是视酷或酷信的二开版本,从底层开始结构就完全不一样, mongodb的库,uniapp混编手端,二开难度 ...

  5. 图片坐标提取软件/图片坐标点和像素点颜色提取软件/图片坐标获取工具/Python图片坐标获取源码/图片像素坐标获取软件/python tkinter 图片显示(完全开源)

    该软件使用python写的,可以提取像素点的坐标还有也能获取像素点的16进制数据RGB565和RGB888(RGB888仅最新的源码才支持),可以单点坐标也可以按键坐标,甚至可以使用简单的左右键配合使 ...

  6. 仿快图系统自带图片浏览器应用源码项目

    仿快图系统自带图片浏览器应用源码,最近在做一个微博i动态模块,需要查看他人相册照片或者微博内容图片等.看到QQ空间那个效果不错,尝试了不少方法来实现,均不是怎么理想.最初是想通过自定义GroupVie ...

  7. Ansroid系统(262)---MTK安卓sim卡相关源码分析

    MTK安卓sim卡相关源码分析 原文地址:http://m.blog.csdn.net/article/details?id=50039589 最近由于一个sim卡相关的需求,就去了解了一下Andro ...

  8. cocos creator2.3.5休闲游戏英文版(连连看)源码H5+安卓+IOS三端源码

    cocos creator2.3.5休闲游戏英文版(连连看)源码H5+安卓+IOS三端源码,开发脚本为typeScript方便扩展和阅读,支持cocos creator2.X版本,完整的源码可直接运营 ...

  9. cocos creator3.3.0休闲游戏(云浮消消乐)源码H5+安卓+IOS三端源码

    cocos creator3.3.0休闲游戏(云浮消消乐)源码H5+安卓+IOS三端源码,开发脚本为typeScript方便扩展和阅读,支持cocos creator3.X版本,完整的源码可直接运营. ...

最新文章

  1. Perl 模块安装遇到的问题解决办法
  2. bash特性之六(bash的快捷键)
  3. The 13th Zhejiang Provincial Collegiate Contest(2016年浙江省赛)
  4. opencv图像拼接_使用OpenCV进行图像全景拼接
  5. Python入门基础篇(五)字符串的正则表达式re模块,全面解析!!!
  6. Qt文档阅读笔记-QtConcurrent Map Example官方实例解析
  7. (转) 淘淘商城系列——使用FastDFS-Client客户端进行上传图片的测试
  8. 你是否需要购买网站重构?
  9. Khronos关于WebGL最新进展
  10. java 遍历 Map 的六种方式 学习笔记
  11. 因子分析在SPSS中的操作过程及结果解读
  12. 2023年深圳市绿色低碳产业扶持计划申报指南
  13. html文字段落加边框线,html边框样式 怎么用html给文字加边框的?
  14. 苹果电脑退出ID账号的方法
  15. 【雅思大作文考官范文】——第十四篇:festivals essay
  16. python实现千牛客服自动回复语_千牛客服自动回复话术
  17. bootrom的类型
  18. 国际象棋AI(三)---评估
  19. 用谷歌浏览器来当手机模拟器
  20. 以本职工作为挡箭牌推托,久而久之,你就只能原地踏步。

热门文章

  1. 苹果手机倒计时不显示
  2. 四种求最大公约数的算法 C / C++
  3. IntelliJ IDEA 字体大小缩放式更改的快捷键设置(很实用!)
  4. python之numpy之伪逆numpy.linalg.pinv
  5. 部分有关会计单词的英中文对照(续)
  6. Date()创建日期
  7. 计算机二级经验总结,计算机二级又考砸了!总结了这些经验,让我重拾信心!...
  8. 百亿业务流量-如何做好稳定性监控
  9. Qt学习总结之Qlineedit
  10. 白鲸优化算法(Beluga whale optimization,BWO)