pointf android 内存,基于Android 实现图片平移、缩放、旋转同时进行

前言

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

需求:

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

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

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

Demo实现部分效果截图

49a9d1c89dc091d38729da8e34273b09.png

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

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中可以使用ImageView控件来显示图片,并且可以通过一些手势识别库,如GestureDetector来实现图片缩放、移动和旋转等操作。以下是一个简单的实现示例: 1. 首先在xml布局文件中添加一个ImageView控件,并设置其src属性为需要显示的图片资源文件: ```xml <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/my_image" /> ``` 2. 在Java代码中,获取ImageView控件的引用,并设置其可缩放、可移动和可旋转: ```java ImageView imageView = findViewById(R.id.imageView); imageView.setScaleType(ImageView.ScaleType.MATRIX); imageView.setOnTouchListener(new TouchListener()); ``` 其中,设置ImageView的ScaleType为MATRIX可以使其支持矩阵变换,从而实现图片缩放、移动和旋转等操作。设置一个TouchListener来监听手势操作。 3. 实现TouchListener中的事件处理方法,用来识别手势操作并执行相应的变换操作: ```java private class TouchListener implements View.OnTouchListener { private Matrix matrix = new Matrix(); private Matrix savedMatrix = new Matrix(); private PointF start = new PointF(); private PointF mid = new PointF(); private float oldDistance; private float oldRotation; @Override public boolean onTouch(View v, MotionEvent event) { ImageView imageView = (ImageView) v; switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); start.set(event.getX(), event.getY()); break; case MotionEvent.ACTION_POINTER_DOWN: oldDistance = getDistance(event); oldRotation = getRotation(event); savedMatrix.set(matrix); getMidPoint(mid, event); break; case MotionEvent.ACTION_MOVE: if (event.getPointerCount() == 1) { matrix.set(savedMatrix); matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); } else if (event.getPointerCount() >= 2) { float newDistance = getDistance(event); float newRotation = getRotation(event); matrix.set(savedMatrix); matrix.postScale(newDistance / oldDistance, newDistance / oldDistance, mid.x, mid.y); matrix.postRotate(newRotation - oldRotation, mid.x, mid.y); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: break; } imageView.setImageMatrix(matrix); return true; } private float getDistance(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 getRotation(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.toDegrees(Math.atan2(y, x)); } private void getMidPoint(PointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); point.set(x / 2, y / 2); } } ``` 其中,onTouch方法中根据不同的手势操作执行相应的矩阵变换操作。用savedMatrix保存当前的矩阵,用matrix进行变换,并将变换后的矩阵设置回ImageView控件中。 这样就可以实现图片缩放、移动和旋转等操作了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值