您的位置:首页 > 移动开发 > Android开发

Android通过OnTouchListener缩放、拖拽ImageView图片

2013-12-05 13:42 507 查看
正在做一个项目,在很多地方有用到图片,要求图片都可以单击(双击)查看大图。在网上找的代码都是直接在activity里设置ImageView 的OnTouchListener事件来实现的。如果有多个地方要用到的话,代码重复量很大,所以自己封装了一下,当然了,OnTouchListener的代码还是在网上借鉴来的,上代码:

package org.vstinspection.activity.uihelper;

import org.vstinspection.utils.AppUtils;

import android.graphics.Bitmap;

import android.graphics.Matrix;

import android.graphics.PointF;

import android.graphics.RectF;

import android.util.FloatMath;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnTouchListener;

import android.widget.ImageView;

public class ImageViewTouchListener implements OnTouchListener {

private ImageView imageView;

private Bitmap bm;

private CustomDialog dialog;

public ImageViewTouchListener(CustomDialog dialog, ImageView imageView,

Bitmap bm) {

this.imageView = imageView;

this.bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth() - 1,

bm.getHeight() - 1);

this.dialog = dialog;

init();

}

private void init() {

center(true,true);

imageView.setImageMatrix(matrix);

}

/** 记录是拖拉照片模式还是放大缩小照片模式 */

private int mode = 0;// 初始状态

/** 拖拉照片模式 */

private static final int MODE_DRAG = 1;

/** 放大缩小照片模式 */

private static final int MODE_ZOOM = 2;

/** 用于记录开始时候的坐标位置 */

private PointF startPoint = new PointF();

/** 用于记录拖拉图片移动的坐标位置 */

private Matrix matrix = new Matrix();

/** 用于记录图片要进行拖拉时候的坐标位置 */

private Matrix currentMatrix = new Matrix();

/** 两个手指的开始距离 */

private float startDis;

/** 两个手指的中间点 */

private PointF midPoint;

@Override

public boolean onTouch(View v, MotionEvent event) {

/** 通过与运算保留最后八位 MotionEvent.ACTION_MASK = 255 */

switch (event.getAction() & MotionEvent.ACTION_MASK) {

// 手指压下屏幕

case MotionEvent.ACTION_DOWN:

if (AppUtils.Utils.isFastDoubleClick(500)) {

dialog.dismiss();

return true;

}

mode = MODE_DRAG;

// 记录ImageView当前的移动位置

currentMatrix.set(imageView.getImageMatrix());

startPoint.set(event.getX(), event.getY());

break;

// 手指在屏幕上移动,改事件会被不断触发

case MotionEvent.ACTION_MOVE:

// 拖拉图片

if (mode == MODE_DRAG) {

float dx = event.getX() - startPoint.x; // 得到x轴的移动距离

float dy = event.getY() - startPoint.y; // 得到x轴的移动距离

// 在没有移动之前的位置上进行移动

matrix.set(currentMatrix);

matrix.postTranslate(dx, dy);

}

// 放大缩小图片

else if (mode == MODE_ZOOM) {

float endDis = distance(event);// 结束距离

if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10

float scale = endDis / startDis;// 得到缩放倍数

matrix.set(currentMatrix);

matrix.postScale(scale, scale, midPoint.x, midPoint.y);

}

}

break;

// 手指离开屏幕

case MotionEvent.ACTION_UP:

// 当触点离开屏幕,但是屏幕上还有触点(手指)

case MotionEvent.ACTION_POINTER_UP:

mode = 0;

break;

// 当屏幕上已经有触点(手指),再有一个触点压下屏幕

case MotionEvent.ACTION_POINTER_DOWN:

mode = MODE_ZOOM;

/** 计算两个手指间的距离 */

startDis = distance(event);

/** 计算两个手指间的中间点 */

if (startDis > 10f) { // 两个手指并拢在一起的时候像素大于10

midPoint = mid(event);

// 记录当前ImageView的缩放倍数

currentMatrix.set(imageView.getImageMatrix());

}

break;

}

imageView.setImageMatrix(matrix);

CheckView();

return true;

}

/** 计算两个手指间的距离 */

private float distance(MotionEvent event) {

float dx = event.getX(1) - event.getX(0);

float dy = event.getY(1) - event.getY(0);

/** 使用勾股定理返回两点之间的距离 */

return FloatMath.sqrt(dx * dx + dy * dy);

}

/** 计算两个手指间的中间点 */

private PointF mid(MotionEvent event) {

float midX = (event.getX(1) + event.getX(0)) / 2;

float midY = (event.getY(1) + event.getY(0)) / 2;

return new PointF(midX, midY);

}

private void CheckView() {

float p[] = new float[9];

matrix.getValues(p);

if (mode == 2) {

if (p[0] < 1f) {

matrix.setScale(1f, 1f);

}

if (p[0] > 4f) {

matrix.setScale(4f, 4f);

}

}

center(true, true);

}

/**

* 横向、纵向居中

*/

protected void center(boolean horizontal, boolean vertical) {

Matrix m = new Matrix();

m.set(matrix);

RectF rect = new RectF(0, 0, bm.getWidth(), bm.getHeight());

m.mapRect(rect);

float height = rect.height();

float width = rect.width();

float deltaX = 0, deltaY = 0;

if (vertical) {

// 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移

int screenHeight = UIHelper.height;

if (height < screenHeight) {

deltaY = (screenHeight - height) / 2 - rect.top;

} else if (rect.top > 0) {

deltaY = -rect.top;

} else if (rect.bottom < screenHeight) {

deltaY = imageView.getHeight() - rect.bottom;

}

}

if (horizontal) {

int screenWidth = UIHelper.width;

if (width < screenWidth) {

deltaX = (screenWidth - width) / 2 - rect.left;

} else if (rect.left > 0) {

deltaX = -rect.left;

} else if (rect.right < screenWidth) {

deltaX = screenWidth - rect.right;

}

}

matrix.postTranslate(deltaX, deltaY);

}

}

ps:我是以弹出Dialog的方式实现的,在dialog里设置ImageView的OnTouchListener

具体用法:

在具体要缩放图片的Activity里调用方法:PopuDialogUtil.popuImageDialog(Context,Bitmap);

public static void popuImageDialog(Context context, Bitmap bm) {

if (bm == null) {

return;

}

final CustomDialog dialog = new CustomDialog(context,

R.layout.imageview1, LayoutParams.MATCH_PARENT,

LayoutParams.MATCH_PARENT);

ImageView imageView = (ImageView) dialog.findViewById(R.id.image);

imageView.setImageBitmap(bm);

imageView.setOnTouchListener(new ImageViewTouchListener(dialog,

imageView, bm));

dialog.show();

}

顺便附上CustomDialog 代码(实现无外/黑框的弹出框)

public CustomDialog(Context context, int layout, int width, int height) {

super(context, R.style.DialogStyle);

setContentView(layout);

Window window = getWindow();

WindowManager.LayoutParams params = window.getAttributes();

params.width = width;

params.height = height;

params.gravity = Gravity.CENTER;

window.setAttributes(params);

setCanceledOnTouchOutside(true);// 点击对话框外部取消对话框显示

}

R.style.DialogStyle:

<style name="DialogStyle" parent="@android:Theme.Dialog">

<item name="android:windowFrame">@null</item>

<item name="android:windowNoTitle">true</item>

<item name="android:windowBackground">@null</item>

<item name="android:windowIsFloating">true</item>

<item name="android:windowContentOverlay">@null</item>

</style>

很详尽吧,不用谢啦~~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: