基于Android 实现图片平移、缩放、旋转同时进行

作者:mrr 时间:2023-05-30 08:30:51 

前言

之前因为项目需求,其中使用到了图片的单击显示取消,图片平移缩放功能,昨天突然想再加上图片的旋转功能,在网上看了很多相关的例子,可是没看到能同时实现我想要的功能的。

需求:

(1)图片平移、缩放、旋转等一系列操作后,图片需要自动居中显示。

(2)图片旋转后选自动水平显示或者垂直显示

(3)图片在放大缩小的同时都能旋转

Demo实现部分效果截图

基于Android 实现图片平移、缩放、旋转同时进行

Demo主要代码

Java


MainActivity.java
package 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();
   }
 }
 @Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   initData();
 }
 public void initData() {
   // TODO Auto-generated method stub
   bm = 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);
   }*/
 }
 @Override
 public 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 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;
 }
 @Override
 protected void onDestroy() {
   // TODO Auto-generated method stub
   super.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 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 2 - width / 2 - rect.left;
   } else if (rect.left > 0) {
     dx = -rect.left;
   } else if (rect.right if (height 2 - height / 2 - rect.top;
   } else if (rect.top > 0) {
     dy = -rect.top;
   } else if (rect.bottom 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 AsyncTaskFile, File, Bitmap> {
   Bitmap bitmap;
   String path;
   int scale = 1;
   long size;
   @Override
   protected Bitmap doInBackground(File... params) {
     // TODO Auto-generated method stub
     try {
       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 block
       e.printStackTrace();
     }
     return bitmap;
   }
   @Override
   protected void onPostExecute(Bitmap result) {
     // TODO Auto-generated method stub
     EventBus.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 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,平移,缩放,旋转
0
投稿

猜你喜欢

  • Linux下java环境配置图文方法

    2021-10-24 06:22:52
  • Android对sdcard扩展卡文件操作实例详解

    2023-12-20 11:34:55
  • Android Application的使用全面解析

    2023-08-26 04:23:49
  • C++二分查找算法实例

    2021-09-07 20:40:05
  • Java设置PDF跨页表格重复显示表头行的步骤详解

    2023-09-21 23:50:33
  • Android自定义渐变式炫酷ListView下拉刷新动画

    2021-12-26 17:31:09
  • flutter使用tauri实现一个一键视频转4K软件

    2022-10-23 05:46:42
  • mybatis中insert主键ID获取和多参数传递的示例代码

    2023-09-20 07:11:00
  • SpringBoot整合Druid数据源过程详解

    2023-06-03 19:47:14
  • C语言 奇偶排序算法详解及实例代码

    2023-04-17 04:47:39
  • Java 替换word文档文字并指定位置插入图片

    2023-08-12 22:02:25
  • Android文本视图TextView实现聊天室效果

    2022-02-15 07:31:55
  • java中关于深拷贝的几种方式总结

    2023-12-13 17:39:41
  • Android Studio实现简易计算器(表格布局TableLayout)

    2021-11-17 23:20:07
  • Flutter 仿微信支付界面

    2023-08-30 01:31:53
  • 深入理解spring boot 监控

    2023-11-04 02:25:15
  • 详解Spring-bean的循环依赖以及解决方式

    2023-08-18 18:30:38
  • JAVA并发编程有界缓存的实现详解

    2022-12-09 16:12:53
  • Java数据结构之单链表详解

    2023-11-04 17:02:20
  • C#遍历文件夹后上传文件夹中所有文件错误案例分析

    2022-11-03 09:28:27
  • asp之家 软件编程 m.aspxhome.com