实现Android图片预览的拖拽缩放
2014-01-19 14:51
525 查看
大多android应用都会有“查看原图”的功能,因原图通常都大于手机屏幕,所以就需要有拖拽,缩放的操作来满足原图的预览。大图预览的一个原则就是:尽量在手机屏幕上居中呈现完整的原图。
由于原图大小和手机屏幕的大小不一,在初始化的时候会出现下面几种处理方式(绿色为手机屏幕,红色为图片)。
1.图片高小于屏幕,宽大于屏幕
2.图片高大于屏幕,宽小于屏幕
3.图片高和宽都小于屏幕
4.图片高和宽都大于屏幕(又分两种情况)
图片的高和宽的缩放都是同比例的,而且所有缩放后的图片都是居中显示的。对图片进行缩放,拖拽时还有校验操作,比如下面的情况:
如果图片和屏幕边框之间有空白,移动图片消除空白部分。
Android实现这些操作的两个必不可少的知识就是onTouch事件,Matrix。通过onTouch事件判断你的手势,通过matrix实现图片的拖拽缩放。
onTouch即屏幕触摸事件,必须知道的几个事件:
MotionEvent.ACTION_DOWN:第一根手指按下
MotionEvent.ACTION_POINTER_DOWN:第二根手指按下
MotionEvent.ACTION_UP:第一根手指离开
MotionEvent.ACTION_POINTER_UP:第二根手指离开
MotionEvent.ACTION_MOVE:手指滑动
拖拽效果的实现:通过MotionEvent.ACTION_DOWN获得第一根手指按下的坐标A,通过MotionEvent.ACTION_MOVE获得滑动后的坐标B,于是便有了A到B的一个偏移,通过这个偏移完成拖拽效果。
缩放效果的实现:通过MotionEvent.ACTION_DOWN获得第一根手指按下的坐标A,通过MotionEvent.ACTION_POINTER_DOWN获得第二根手指按下的坐标B,于是便有了两点间距AB1。通过MotionEvent.ACTION_MOVE会获得新的A,B两点间距AB2。通过AB2/AB1的值便得知缩放比例。
Matrix没什么可说的,看看API都明白了。有一点要注意的是matrix.postXXX方法指的是在当前matirx基础上进行相应操作,matrix.setXXX是初始化当前matrix后进行的相应操作。
实现代码:
XML:
android:scaleType="matrix",这句话是重点
J***A:
由于原图大小和手机屏幕的大小不一,在初始化的时候会出现下面几种处理方式(绿色为手机屏幕,红色为图片)。
1.图片高小于屏幕,宽大于屏幕
2.图片高大于屏幕,宽小于屏幕
3.图片高和宽都小于屏幕
4.图片高和宽都大于屏幕(又分两种情况)
图片的高和宽的缩放都是同比例的,而且所有缩放后的图片都是居中显示的。对图片进行缩放,拖拽时还有校验操作,比如下面的情况:
如果图片和屏幕边框之间有空白,移动图片消除空白部分。
Android实现这些操作的两个必不可少的知识就是onTouch事件,Matrix。通过onTouch事件判断你的手势,通过matrix实现图片的拖拽缩放。
onTouch即屏幕触摸事件,必须知道的几个事件:
MotionEvent.ACTION_DOWN:第一根手指按下
MotionEvent.ACTION_POINTER_DOWN:第二根手指按下
MotionEvent.ACTION_UP:第一根手指离开
MotionEvent.ACTION_POINTER_UP:第二根手指离开
MotionEvent.ACTION_MOVE:手指滑动
拖拽效果的实现:通过MotionEvent.ACTION_DOWN获得第一根手指按下的坐标A,通过MotionEvent.ACTION_MOVE获得滑动后的坐标B,于是便有了A到B的一个偏移,通过这个偏移完成拖拽效果。
缩放效果的实现:通过MotionEvent.ACTION_DOWN获得第一根手指按下的坐标A,通过MotionEvent.ACTION_POINTER_DOWN获得第二根手指按下的坐标B,于是便有了两点间距AB1。通过MotionEvent.ACTION_MOVE会获得新的A,B两点间距AB2。通过AB2/AB1的值便得知缩放比例。
Matrix没什么可说的,看看API都明白了。有一点要注意的是matrix.postXXX方法指的是在当前matirx基础上进行相应操作,matrix.setXXX是初始化当前matrix后进行的相应操作。
实现代码:
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ShowImage" > <ImageView android:id="@+id/imgv" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="matrix" /> </RelativeLayout>
android:scaleType="matrix",这句话是重点
J***A:
package com.example.showimgdemo; 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.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; public class ShowImage extends Activity implements OnTouchListener { private ImageView imgv; private PointF point0 = new PointF(); private PointF pointM = new PointF(); private final float ZOOM_MIN_SPACE = 10f; // 设定事件模式 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(); // 获取屏幕分辨率。以480*320为例 private int displayHeight = 480; private int displayWidth = 320; private float minScale = 1f; private float maxScale = 10f; private float currentScale = 1f; private float oldDist; private Bitmap bm; private int imgWidth; private int imgHeight; @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); setContentView(R.layout.show_image); init(); } private void init() { imgv = (ImageView) findViewById(R.id.imgv); imgv.setOnTouchListener(this); bm = BitmapFactory.decodeResource(getResources(), R.drawable.test2); imgWidth = bm.getWidth(); imgHeight = bm.getHeight(); imgv.setImageBitmap(bm); minScale = getMinScale(); matrix.setScale(minScale, minScale); center(); imgv.setImageMatrix(matrix); } @Override public boolean onTouch(View v, MotionEvent event) { ImageView imgv = (ImageView) v; switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); point0.set(event.getX(), event.getY()); mode = DRAG; break; case MotionEvent.ACTION_POINTER_DOWN: oldDist = spacing(event); if (oldDist > ZOOM_MIN_SPACE) { savedMatrix.set(matrix); setMidPoint(event); mode = ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; break; case MotionEvent.ACTION_MOVE: whenMove(event); break; } imgv.setImageMatrix(matrix); checkView(); return true; } private void whenMove(MotionEvent event) { switch (mode) { case DRAG: matrix.set(savedMatrix); matrix.postTranslate(event.getX() - point0.x, event.getY() - point0.y); break; case ZOOM: float newDist = spacing(event); if (newDist > ZOOM_MIN_SPACE) { matrix.set(savedMatrix); float sxy = newDist / oldDist; System.out.println(sxy + "<==放大缩小倍数"); matrix.postScale(sxy, sxy, pointM.x, pointM.y); } break; } } // 两个触点的距离 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 void setMidPoint(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 center() { 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 < displayWidth) dx = displayWidth / 2 - width / 2 - rect.left; else if (rect.left > 0) dx = -rect.left; else if (rect.right < displayWidth) dx = displayWidth - rect.right; if (height < displayHeight) dy = displayHeight / 2 - height / 2 - rect.top; else if (rect.top > 0) dy = -rect.top; else if (rect.bottom < displayHeight) dy = displayHeight - rect.bottom; matrix.postTranslate(dx, dy); } // 获取最小缩放比例 private float getMinScale() { float sx = (float) displayWidth / imgWidth; float sy = (float) displayHeight / imgHeight; float scale = sx < sy ? sx : sy; if (scale > 1) { scale = 1f; } return scale; } // 检查约束条件,是否居中,空间显示是否合理 private void checkView() { currentScale = getCurrentScale(); if (mode == ZOOM) { if (currentScale < minScale) { matrix.setScale(minScale, minScale); } if (currentScale > maxScale) { matrix.set(savedMatrix); } } center(); } // 图片当前的缩放比例 private float getCurrentScale() { float[] values = new float[9]; matrix.getValues(values); return values[Matrix.MSCALE_X]; } }
相关文章推荐
- Android实现本地图片选择及预览缩放效果仿春雨医生
- Android自定义View实现图片显示,并实现缩放、拖拽、切换功能
- android imageview 多点触碰(MultiTouch)实现图片拖拽移动缩放
- android自定义图片,支持缩放拖拽的功能实现
- Android多点触摸实现缩放和拖拽图片
- Android 在viewPager中双指缩放图片双击缩放图片单指拖拽图片的实现思路
- android 大图片拖拽并缩放实现原理
- Android实现本地图片选择及预览缩放效果
- android imageview 多点触碰(MultiTouch)实现图片拖拽移动缩放
- Android-图片预览(自定义ImageView实现图片缩放,多点触控,自由移动)
- Android:利用Matrix,实现双手指缩放图片与拖拽图片功能
- android 大图片拖拽并缩放实现原理
- android imageview 多点触碰(MultiTouch)实现图片拖拽移动缩放
- Android实现图片上传,可以选择多张图片,缩放预览,拍照上传等
- Android实现图片预览浏览功能
- Android开发之imageView图片按比例缩放的实现方法
- Android 手势检测实战 打造支持缩放平移的图片预览效果(下)
- Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
- Android图片预览效果,支持缩放、平移切换
- 【Android 开发】:UI控件之 ImageView 实现图片旋转和缩放功能