欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-05 15:17:58
前言 之前因为项目需求,其中使用到了图片的单击显示取消,图片平移缩放功能,昨天突然想再加上图片的旋转功能,在网上看了很多相关的例子,可是没看到能同时实现我想要的功能的。...

前言

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

需求:

(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
  }
}