转载请注明转自:noyet12的博客
博客原址:http://blog.csdn.net/u012975705/article/details/49797911
源码下载地址:
(github)https://github.com/noyo/RotateZoomImageView
(csdn)http://download.csdn.net/detail/u012975705/9263323
EventBus2.4.jar下载

前言

之前因为项目需求,其中使用到了图片的单击显示取消,图片平移缩放功能,昨天突然想再加上图片的旋转功能,在网上看了很多相关的例子,可是没看到能同时实现我想要的功能的。
需求:
(1)图片平移、缩放、旋转等一系列操作后,图片需要自动居中显示。
(2)图片旋转后选自动水平显示或者垂直显示
(3)图片在放大缩小的同时都能旋转

Demo实现部分效果截图

Demo主要代码

MainActivity.javapackage com.practice.noyet.rotatezoomimageview;import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;import com.ypy.eventbus.EventBus;import java.io.File;
import java.math.BigDecimal;/*** package: com.practice.noyet.rotatezoomimageview* Created by noyet on 2015/11/11.*/
public class MainActivity extends Activity implements View.OnTouchListener {private ImageView mImageView;private PointF point0 = new PointF();private PointF pointM = new PointF();private final int NONE = 0;/*** 平移*/private final int DRAG = 1;/*** 旋转、缩放*/private final int ZOOM = 2;/*** 设定事件模式*/private int mode = NONE;/*** 图片缩放矩阵*/private Matrix matrix = new Matrix();/*** 保存触摸前的图片缩放矩阵*/private Matrix savedMatrix = new Matrix();/*** 保存触点移动过程中的图片缩放矩阵*/private Matrix matrix1 = new Matrix();/*** 屏幕高度*/private int displayHeight;/*** 屏幕宽度*/private int displayWidth;/*** 最小缩放比例*/protected float minScale = 1f;/*** 最大缩放比例*/protected float maxScale = 3f;/*** 当前缩放比例*/protected float currentScale = 1f;/*** 多点触摸2个触摸点间的起始距离*/private float oldDist;/*** 多点触摸时图片的起始角度*/private float oldRotation = 0;/*** 旋转角度*/protected float rotation = 0;/*** 图片初始宽度*/private int imgWidth;/*** 图片初始高度*/private int imgHeight;/*** 设置单点触摸退出图片显示时,单点触摸的灵敏度(可针对不同手机单独设置)*/protected final int MOVE_MAX = 2;/*** 单点触摸时手指触发的‘MotionEvent.ACTION_MOVE’次数*/private int fingerNumMove = 0;private Bitmap bm;/*** 保存matrix缩放比例*/private float matrixScale= 1;/*private String imagePath;*//*** 显示被存入缓存中的网络图片** @param event 观察者事件*/public void onEventMainThread(CustomEventBus event) {if (event == null) {return;}if (event.type == CustomEventBus.EventType.SHOW_PICTURE) {bm = (Bitmap) event.obj;showImage();}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initData();}public void initData() {// TODO Auto-generated method stubbm = BitmapFactory.decodeResource(getResources(), R.drawable.alipay);DisplayMetrics dm = getResources().getDisplayMetrics();displayWidth = dm.widthPixels;displayHeight = dm.heightPixels;mImageView = (ImageView) findViewById(R.id.image_view);mImageView.setOnTouchListener(this);showImage();//显示网络图片时使用/*File file = MainApplication.getInstance().getImageCache().getDiskCache().get(图片路径);if (!file.exists()) {Toast.makeText(this, "图片路径错误", Toast.LENGTH_SHORT).show();} else {new MyTask().execute(file);}*/}@Overridepublic boolean onTouch(View view, MotionEvent event) {ImageView imageView = (ImageView) view;switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_DOWN:savedMatrix.set(matrix);point0.set(event.getX(), event.getY());mode = DRAG;System.out.println("MotionEvent--ACTION_DOWN");break;case MotionEvent.ACTION_POINTER_DOWN:oldDist = spacing(event);oldRotation = rotation(event);savedMatrix.set(matrix);setMidPoint(pointM, event);mode = ZOOM;System.out.println("MotionEvent--ACTION_POINTER_DOWN---" + oldRotation);break;case MotionEvent.ACTION_UP:if (mode == DRAG && (fingerNumMove <= MOVE_MAX)) {MainActivity.this.finish();}checkView();centerAndRotate();imageView.setImageMatrix(matrix);System.out.println("MotionEvent--ACTION_UP");fingerNumMove = 0;break;case MotionEvent.ACTION_POINTER_UP:mode = NONE;System.out.println("MotionEvent--ACTION_POINTER_UP");break;case MotionEvent.ACTION_MOVE:operateMove(event);imageView.setImageMatrix(matrix1);fingerNumMove++;System.out.println("MotionEvent--ACTION_MOVE");break;}return true;}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();if (bm != null && !bm.isRecycled()) {bm.recycle(); // 回收图片所占的内存System.gc(); // 提醒系统及时回收}}/*** 显示图片*/private void showImage() {imgWidth = bm.getWidth();imgHeight = bm.getHeight();mImageView.setImageBitmap(bm);matrix.setScale(1, 1);centerAndRotate();mImageView.setImageMatrix(matrix);}/*** 触点移动时的操作** @param event 触摸事件*/private void operateMove(MotionEvent event) {matrix1.set(savedMatrix);switch (mode) {case DRAG:matrix1.postTranslate(event.getX() - point0.x, event.getY() - point0.y);break;case ZOOM:rotation = rotation(event) - oldRotation;float newDist = spacing(event);float scale = newDist / oldDist;currentScale = (scale > 3.5f) ? 3.5f : scale;System.out.println("缩放倍数---" + currentScale);System.out.println("旋转角度---" + rotation);/** 縮放 */matrix1.postScale(currentScale, currentScale, pointM.x, pointM.y);/** 旋轉 */matrix1.postRotate(rotation, displayWidth / 2, displayHeight / 2);break;}}/*** 两个触点的距离** @param event 触摸事件* @return float*/private float spacing(MotionEvent event) {float x = event.getX(0) - event.getX(1);float y = event.getY(0) - event.getY(1);return (float) Math.sqrt(x * x + y * y);}/*** 获取旋转角度*/private float rotation(MotionEvent event) {double delta_x = (event.getX(0) - event.getX(1));double delta_y = (event.getY(0) - event.getY(1));double radians = Math.atan2(delta_y, delta_x);return (float) Math.toDegrees(radians);}/*** 两个触点的中间坐标** @param pointM 中间坐标* @param event  触摸事件*/private void setMidPoint(PointF pointM, MotionEvent event) {float x = event.getX(0) + event.getY(1);float y = event.getY(0) + event.getY(1);pointM.set(x / 2, y / 2);}/*** 检查约束条件(缩放倍数)*/private void checkView() {if (currentScale > 1) {if (currentScale * matrixScale > maxScale) {matrix.postScale(maxScale / matrixScale, maxScale / matrixScale, pointM.x, pointM.y);matrixScale = maxScale;} else {matrix.postScale(currentScale, currentScale, pointM.x, pointM.y);matrixScale *= currentScale;}} else {if (currentScale * matrixScale < minScale) {matrix.postScale(minScale / matrixScale, minScale / matrixScale, pointM.x, pointM.y);matrixScale = minScale;} else {matrix.postScale(currentScale, currentScale, pointM.x, pointM.y);matrixScale *= currentScale;}}}/*** 图片居中显示、判断旋转角度 小于(90 * x + 45)度图片旋转(90 * x)度 大于则旋转(90 * (x+1))*/private void centerAndRotate() {RectF rect = new RectF(0, 0, imgWidth, imgHeight);matrix.mapRect(rect);float width = rect.width();float height = rect.height();float dx = 0;float dy = 0;if (width < displayWidth) {dx = displayWidth / 2 - width / 2 - rect.left;} else if (rect.left > 0) {dx = -rect.left;} else if (rect.right < displayWidth) {dx = displayWidth - rect.right;}if (height < displayHeight) {dy = displayHeight / 2 - height / 2 - rect.top;} else if (rect.top > 0) {dy = -rect.top;} else if (rect.bottom < displayHeight) {dy = displayHeight - rect.bottom;}matrix.postTranslate(dx, dy);if (rotation != 0) {int rotationNum = (int) (rotation / 90);float rotationAvai = new BigDecimal(rotation % 90).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();float realRotation = 0;if (rotation > 0) {realRotation = rotationAvai > 45 ? (rotationNum + 1) * 90 : rotationNum * 90;} else if (rotation < 0) {realRotation = rotationAvai < -45 ? (rotationNum - 1) * 90 : rotationNum * 90;}System.out.println("realRotation: " + realRotation);matrix.postRotate(realRotation, displayWidth / 2, displayHeight / 2);rotation = 0;}}/*** 显示网络图片时使用*/private class MyTask extends AsyncTask<File, File, Bitmap> {Bitmap bitmap;String path;int scale = 1;long size;@Overrideprotected Bitmap doInBackground(File... params) {// TODO Auto-generated method stubtry {size = params[0].length();path = params[0].getAbsolutePath();BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(path, options);scale = calculateInSampleSize(options, displayWidth,displayHeight);options.inJustDecodeBounds = false;options.inSampleSize = scale;bitmap = BitmapFactory.decodeFile(path, options);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return bitmap;}@Overrideprotected void onPostExecute(Bitmap result) {// TODO Auto-generated method stubEventBus.getDefault().post(new CustomEventBus(CustomEventBus.EventType.SHOW_PICTURE, result));}/*** 获取图片缩放比例** @param paramOptions Options* @param paramInt1    宽* @param paramInt2    高* @return int*/private int calculateInSampleSize(BitmapFactory.Options paramOptions,int paramInt1, int paramInt2) {int i = paramOptions.outHeight;int j = paramOptions.outWidth;int k = 1;if ((i > paramInt2) || (j > paramInt1)) {int m = Math.round(i / paramInt2);int n = Math.round(j / paramInt1);k = m < n ? n : m;}return k;}}
}
CustomEventBus.java
package com.practice.noyet.rotatezoomimageview;/*** package: com.practice.noyet.rotatezoomimageview* Created by noyet on 2015/11/11.*/
public class CustomEventBus {public EventType type;public Object obj;public CustomEventBus(EventType type, Object obj) {this.type = type;this.obj = obj;}enum EventType {SHOW_PICTURE}
}

Android中实现图片平移、缩放、旋转同步进行相关推荐

  1. python + pyqt +opencv 有界面,对lable中的图片进行图像旋转,向右平移,向下平移,二值化,灰度,边缘检测

    对lable中的图片进行图像旋转,向右平移,向下平移,二值化,灰度,边缘检测 要求: 一个界面,具体界面内容自行设计但必须符合以下要求 多个操作按钮: 1.图像180°旋转 2.图像向右平移 3.图像 ...

  2. qgraphicsview鼠标移动图片_交互式QGraphicsView(平移/缩放/旋转)-阿里云开发者社区...

    简述 Graphics View提供了一个平台用于大量自定义 2D 图元的管理与交互框架包括一个事件传播架构支持场景 Scene 中的图元 Item 进行精确的双精度交互功能.Item 可以处理键盘事 ...

  3. [Python从零到壹] 三十八.图像处理基础篇之图像几何变换(平移缩放旋转)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  4. Android中对图片的内存优化方法

    Android 中对于图片的内存优化方法 1. 对图片本身进行操作 尽量不要使用 setImageBitmap.setImageResource.BitmapFactory.decodeResourc ...

  5. Android 中定义图片的资源文件

    ---恢复内容开始--- Android中定义图片的Id数组可以在java代码中直接通过new定义,之后使用,还有一种方法是在xml资源文件中直接定义,然后再java代码中通过函数可以获取xml代码中 ...

  6. 【Android】Android 中定义图片的资源文件

    Android中定义图片的Id数组可以在java代码中直接通过new定义,之后使用,还有一种方法是在xml资源文件中直接定义,然后再java代码中通过函数可以获取xml代码中定义的资源文件.当然第二中 ...

  7. android图片美化开源,GitHub - xingxing-yan/BLImage: Android中美化图片的库。功能包括滤镜,贴纸,标签,裁剪,涂鸦,亮度,饱和度,对比度,马赛克等功能...

    BLImage Android中美化图片的库.功能包括滤镜,贴纸,标签,裁剪,涂鸦,亮度,饱和度,对比度,马赛克等功能 效果图 添加依赖: 在project的build.gradle中添加: allp ...

  8. Android中的图片加载

    Android中的图片加载所出现的问题 在Android的开发中,经常需要去加载图片,但是图片的尺寸有时候往往会很大,而我们的内存是有限的,加载进来的时候很有可能会造成内存溢出,这种结果也是我们不想看 ...

  9. 浅谈android中的图片处理之基本绘图(一)

    从今天开始我来聊下关于android中的图片处理以及android中绘图的基本用法.大家都知道android中的图片的巧妙使用会给UI得到一个很好的用户体验.所以掌握处理图片的基本技巧很是重要.那就开 ...

最新文章

  1. kerberos java实现,基于kerberos实现jaas登录
  2. 从1400篇机器学习文章中精选出Top 10,帮你找找上班的感觉!
  3. ibatis时间比较大小
  4. CPU分时、中断和上下文切换
  5. mysql 自带 数据库_mysql自带的4个数据库介绍
  6. C#-invoke与sendmessage,findWindow的阻塞实验
  7. 《零基础看得懂的C++入门教程 》——(9)结构体原来如此
  8. IPC 中 LPC、RPC 的区别和联系
  9. 第八篇:Spring Boot整合Thymeleaf_入门试炼04
  10. 百度文库崩溃半小时:赶论文的网友也集体崩了
  11. 《Adobe Premiere Pro CC经典教程》——6.2 节目监视器控件
  12. 反编译工具ILSpy的下载与使用
  13. 软件测试入门之测试项目启动与研读需求文档(精辟干货)
  14. vs 2019怎么运行单个的cpp文件以及报错main已存在解决方法
  15. 【基础入门题048】骰子游戏(一)
  16. 【转载】在美国找工作秘籍
  17. 属牛的女孩取名:优美文雅、声声入耳的女孩名字
  18. turtle画分形树
  19. HTML|下拉框和文本域、文件域
  20. python全0列表_Python 列表(Lists)

热门文章

  1. mysql master 重置_[数据库]重置mysql主从同步(MySQL Reset Master
  2. MSSQL数据库的字段类型总结
  3. swift 中加载nib两种方式
  4. Java面试题大全(整理版)1000+面试题附答案详解,最全面详细,看完不进你找我
  5. json to excel java_java解析json生成excel
  6. 电脑开不了机计算机无法启动,电脑中毒了开不了机怎么回事_电脑中毒无法开机的解决步骤-win7之家...
  7. Java8两个list集合合并成一个list集合
  8. Python合并两个列表,使两个列表拼接起来
  9. android 10.0 展讯 MTK内置可卸载app
  10. 走遍美国 —— 各州及其别名