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

原创 2013年12月05日 13:42:42

正在做一个项目,在很多地方有用到图片,要求图片都可以单击(双击)查看大图。在网上找的代码都是直接在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>

很详尽吧,不用谢啦~~~~

[Android] 触屏setOnTouchListener实现图片缩放、移动、绘制和添加水印

本文主要讲述使用触屏实现图片缩放、移动、添加水印等功能,所以该篇文章主要通过setOnTouchListener监听实现该功能,如何使用RelativeLayout进行布局,MotionEvent.A...
  • Eastmount
  • Eastmount
  • 2014年10月28日 17:57
  • 6314

android-ImageView的拖动、旋转、缩放、边界回弹、双击缩放、单击销毁及源码下载

博客地址:http://blog.csdn.net/u010156024 TouchImageViewActivity 是本人一句一句代码写的,参考了网上大牛的博客。 不过其中的效果是网上没有的,...
  • u010156024
  • u010156024
  • 2015年08月29日 17:20
  • 4487

Android 自定义ImageView支持缩放,拖拽,方便复用

今天刚发了一篇关于ImageView的缩放和拖拽的博客,然后我想了下,将他自定义下,方便我们来复用这个imageView,效果我就不多说了,http://blog.csdn.net/xiaanming...
  • xiaanming
  • xiaanming
  • 2013年04月20日 17:35
  • 31097

Android imageview 多点触碰(MultiTouch)实现图片拖拽移动缩放

  • 2016年07月06日 13:40
  • 2.51MB
  • 下载

android imageview 多点触碰(MultiTouch)实现图片拖拽移动缩放

刚用android手机 发现手机自带的图片浏览器挺酷 可以用手指移动 缩放 还有动画效果        Intent intent = new Intent(Intent.ACTION_VIEW);...
  • zhangsheXIN_
  • zhangsheXIN_
  • 2013年11月15日 14:38
  • 888

ImageView(三)---拖拽+两点触碰缩放图片

转自:http://blog.csdn.net/guolin_blog/article/details/11100327 在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果,虽然...
  • icedcap
  • icedcap
  • 2014年03月19日 20:21
  • 677

Android 自定义ImageView支持缩放,拖拽,方便复用

今天刚发了一篇关于ImageView的缩放和拖拽的博客,然后我想了下,将他自定义下,方便我们来复用这个imageView,效果我就不多说了,http://blog.csdn.net/xiaanming...
  • xiaanming
  • xiaanming
  • 2013年04月20日 17:35
  • 31097

android手势缩放和拖拽图片

  • 2015年04月22日 17:16
  • 4.41MB
  • 下载

Android 多点触控,多张图片拖拽,缩放,旋转

  • 2015年05月27日 16:35
  • 5.68MB
  • 下载

Android对图片进行拖拽和缩放

  • 2014年05月09日 23:36
  • 564KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android通过OnTouchListener缩放、拖拽ImageView图片
举报原因:
原因补充:

(最多只允许输入30个字)