<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" > <ImageView android:id="@+id/imag" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:scaleType="matrix" > </ImageView> </FrameLayout>
Android 图片的浏览、缩放、拖动和自动居中
转载地址:http://www.cnblogs.com/dwinter/archive/2012/01/12/2321082.html
- Touch.java
/** * 图片浏览、缩放、拖动、自动居中 */ public class Touch extends Activity implements OnTouchListener { Matrix matrix = new Matrix(); Matrix savedMatrix = new Matrix(); DisplayMetrics dm; ImageView imgView; Bitmap bitmap; float minScaleR;// 最小缩放比例 static final float MAX_SCALE = 4f;// 最大缩放比例 static final int NONE = 0;// 初始状态 static final int DRAG = 1;// 拖动 static final int ZOOM = 2;// 缩放 int mode = NONE; PointF prev = new PointF(); PointF mid = new PointF(); float dist = 1f; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scale); imgView = (ImageView) findViewById(R.id.imag);// 获取控件 bitmap = BitmapFactory.decodeResource(getResources(), this.getIntent() .getExtras().getInt("IMG"));// 获取图片资源 imgView.setImageBitmap(bitmap);// 填充控件 imgView.setOnTouchListener(this);// 设置触屏监听 dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm);// 获取分辨率 minZoom(); center(); imgView.setImageMatrix(matrix); } /** * 触屏监听 */ public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { // 主点按下 case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); prev.set(event.getX(), event.getY()); mode = DRAG; break; // 副点按下 case MotionEvent.ACTION_POINTER_DOWN: dist = spacing(event); // 如果连续两点距离大于10,则判定为多点模式 if (spacing(event) > 10f) { savedMatrix.set(matrix); midPoint(mid, event); mode = ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { matrix.set(savedMatrix); matrix.postTranslate(event.getX() - prev.x, event.getY() - prev.y); } else if (mode == ZOOM) { float newDist = spacing(event); if (newDist > 10f) { matrix.set(savedMatrix); float tScale = newDist / dist; matrix.postScale(tScale, tScale, mid.x, mid.y); } } break; } imgView.setImageMatrix(matrix); CheckView(); return true; } /** * 限制最大最小缩放比例,自动居中 */ private void CheckView() { float p[] = new float[9]; matrix.getValues(p); if (mode == ZOOM) { if (p[0] < minScaleR) { matrix.setScale(minScaleR, minScaleR); } if (p[0] > MAX_SCALE) { matrix.set(savedMatrix); } } center(); } /** * 最小缩放比例,最大为100% */ private void minZoom() { minScaleR = Math.min( (float) dm.widthPixels / (float) bitmap.getWidth(), (float) dm.heightPixels / (float) bitmap.getHeight()); if (minScaleR < 1.0) { matrix.postScale(minScaleR, minScaleR); } } private void center() { center(true, true); } /** * 横向、纵向居中 */ protected void center(boolean horizontal, boolean vertical) { Matrix m = new Matrix(); m.set(matrix); RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); m.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; if (vertical) { // 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移 int screenHeight = dm.heightPixels; if (height < screenHeight) { deltaY = (screenHeight - height) / 2 - rect.top; } else if (rect.top > 0) { deltaY = -rect.top; } else if (rect.bottom < screenHeight) { deltaY = imgView.getHeight() - rect.bottom; } } if (horizontal) { int screenWidth = dm.widthPixels; 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); } /** * 两点的距离 */ private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return FloatMath.sqrt(x * x + y * y); } /** * 两点的中点 */ private void midPoint(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); } }
- scale.xml
android Matrix图片随意的放大缩小,拖动
转载地址:http://www.bdqn.cn/news/201304/8794.shtml
step1:新建一个项目DragAndZoom,并准备一张照片放在res/drawable-hdpi目录下,如下图所示:
(图片略)
step2: 设置应用的UI界面,在main.xml中设置:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/wall" android:id="@+id/imageView" android:scaleType="matrix" /> <!-- 指定为matrix类型 --> </LinearLayout>
step3:MainActivity.java中实现具体的需求
package cn.roco.drag; import android.app.Activity; import android.graphics.Matrix; import android.graphics.PointF; import android.os.Bundle; import android.util.FloatMath; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; public class MainActivity extends Activity { private ImageView imageView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imageView = (ImageView) this.findViewById(R.id.imageView); imageView.setOnTouchListener(new TouchListener()); } private final class TouchListener implements OnTouchListener { /** 记录是拖拉照片模式还是放大缩小照片模式 */ 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: 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); 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); } } }
step4:AndroidMainfest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.roco.drag" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>