首页 > 系统 > Android > 正文

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

2020-04-11 11:16:43
字体:
来源:转载
供稿:网友

前言

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

需求:

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

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

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

Demo实现部分效果截图

Demo主要代码

Java

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();    }  }  @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.javapackage 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  }}

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表