我的Android进阶之旅------>android Matrix图片随意的放大缩小,拖动(转)

step1:新建一个项目DragAndZoom,并准备一张照片放在res/drawable-hdpi目录下,如下图所示:

       

step2: 设置应用的UI界面,在main.xml中设置:

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <ImageView    
  8.     android:layout_width="fill_parent"   
  9.     android:layout_height="wrap_content"   
  10.     android:src="@drawable/wall"  
  11.     android:id="@+id/imageView"  
  12.     android:scaleType="matrix"     
  13.     />  <!-- 指定为matrix类型 -->  
  14. </LinearLayout>  


step3:MainActivity.java中实现具体的需求

 

 

[java] view plain copy
 
  1. package cn.roco.drag;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Matrix;  
  5. import android.graphics.PointF;  
  6. import android.os.Bundle;  
  7. import android.util.FloatMath;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.View.OnTouchListener;  
  11. import android.widget.ImageView;  
  12.   
  13. public class MainActivity extends Activity {  
  14.   
  15.     private ImageView imageView;  
  16.   
  17.     @Override  
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.   
  22.         imageView = (ImageView) this.findViewById(R.id.imageView);  
  23.         imageView.setOnTouchListener(new TouchListener());  
  24.     }  
  25.   
  26.     private final class TouchListener implements OnTouchListener {  
  27.           
  28.         /** 记录是拖拉照片模式还是放大缩小照片模式 */  
  29.         private int mode = 0;// 初始状态    
  30.         /** 拖拉照片模式 */  
  31.         private static final int MODE_DRAG = 1;  
  32.         /** 放大缩小照片模式 */  
  33.         private static final int MODE_ZOOM = 2;  
  34.           
  35.         /** 用于记录开始时候的坐标位置 */  
  36.         private PointF startPoint = new PointF();  
  37.         /** 用于记录拖拉图片移动的坐标位置 */  
  38.         private Matrix matrix = new Matrix();  
  39.         /** 用于记录图片要进行拖拉时候的坐标位置 */  
  40.         private Matrix currentMatrix = new Matrix();  
  41.       
  42.         /** 两个手指的开始距离 */  
  43.         private float startDis;  
  44.         /** 两个手指的中间点 */  
  45.         private PointF midPoint;  
  46.   
  47.         @Override  
  48.         public boolean onTouch(View v, MotionEvent event) {  
  49.             /** 通过与运算保留最后八位 MotionEvent.ACTION_MASK = 255 */  
  50.             switch (event.getAction() & MotionEvent.ACTION_MASK) {  
  51.             // 手指压下屏幕  
  52.             case MotionEvent.ACTION_DOWN:  
  53.                 mode = MODE_DRAG;  
  54.                 // 记录ImageView当前的移动位置  
  55.                 currentMatrix.set(imageView.getImageMatrix());  
  56.                 startPoint.set(event.getX(), event.getY());  
  57.                 break;  
  58.             // 手指在屏幕上移动,改事件会被不断触发  
  59.             case MotionEvent.ACTION_MOVE:  
  60.                 // 拖拉图片  
  61.                 if (mode == MODE_DRAG) {  
  62.                     float dx = event.getX() - startPoint.x; // 得到x轴的移动距离  
  63.                     float dy = event.getY() - startPoint.y; // 得到x轴的移动距离  
  64.                     // 在没有移动之前的位置上进行移动  
  65.                     matrix.set(currentMatrix);  
  66.                     matrix.postTranslate(dx, dy);  
  67.                 }  
  68.                 // 放大缩小图片  
  69.                 else if (mode == MODE_ZOOM) {  
  70.                     float endDis = distance(event);// 结束距离  
  71.                     if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10  
  72.                         float scale = endDis / startDis;// 得到缩放倍数  
  73.                         matrix.set(currentMatrix);  
  74.                         matrix.postScale(scale, scale,midPoint.x,midPoint.y);  
  75.                     }  
  76.                 }  
  77.                 break;  
  78.             // 手指离开屏幕  
  79.             case MotionEvent.ACTION_UP:  
  80.                 // 当触点离开屏幕,但是屏幕上还有触点(手指)  
  81.             case MotionEvent.ACTION_POINTER_UP:  
  82.                 mode = 0;  
  83.                 break;  
  84.             // 当屏幕上已经有触点(手指),再有一个触点压下屏幕  
  85.             case MotionEvent.ACTION_POINTER_DOWN:  
  86.                 mode = MODE_ZOOM;  
  87.                 /** 计算两个手指间的距离 */  
  88.                 startDis = distance(event);  
  89.                 /** 计算两个手指间的中间点 */  
  90.                 if (startDis > 10f) { // 两个手指并拢在一起的时候像素大于10  
  91.                     midPoint = mid(event);  
  92.                     //记录当前ImageView的缩放倍数  
  93.                     currentMatrix.set(imageView.getImageMatrix());  
  94.                 }  
  95.                 break;  
  96.             }  
  97.             imageView.setImageMatrix(matrix);  
  98.             return true;  
  99.         }  
  100.   
  101.         /** 计算两个手指间的距离 */  
  102.         private float distance(MotionEvent event) {  
  103.             float dx = event.getX(1) - event.getX(0);  
  104.             float dy = event.getY(1) - event.getY(0);  
  105.             /** 使用勾股定理返回两点之间的距离 */  
  106.             return FloatMath.sqrt(dx * dx + dy * dy);  
  107.         }  
  108.   
  109.         /** 计算两个手指间的中间点 */  
  110.         private PointF mid(MotionEvent event) {  
  111.             float midX = (event.getX(1) + event.getX(0)) / 2;  
  112.             float midY = (event.getY(1) + event.getY(0)) / 2;  
  113.             return new PointF(midX, midY);  
  114.         }  
  115.   
  116.     }  
  117.   
  118. }  


step4:AndroidMainfest.xml

 

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="cn.roco.drag"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <uses-sdk android:minSdkVersion="8" />  
  7.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name=".MainActivity"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.   
  17.     </application>  
  18. </manifest>  


step5:具体的效果图

 

                               

上面两个是图片拖拽的效果,而图片的缩放效果要在真机中才能够看得到,请读者自己在真机环境中测试。

 

附注:具体的程序源码在:http://pan.baidu.com/share/link?shareid=397888&uk=805959799

 

 

 

 

其实 通过通过手势也可以缩放图片    左--->右 放大 右 --->左 缩小 速度越快,缩放比例越大

zoom.xml

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <ImageView    
  8.     android:layout_width="fill_parent"   
  9.     android:layout_height="wrap_content"   
  10.     android:src="@drawable/wall"  
  11.     android:id="@+id/show"  
  12.     android:scaleType="matrix"     
  13.     />  <!-- 指定为matrix类型 -->  
  14. </LinearLayout>  

 

 

GestureZoom.java

 

[java] view plain copy
 
  1. package cn.roco.gesture;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.BitmapFactory;  
  6. import android.graphics.Matrix;  
  7. import android.graphics.drawable.BitmapDrawable;  
  8. import android.os.Bundle;  
  9. import android.view.GestureDetector;  
  10. import android.view.GestureDetector.OnGestureListener;  
  11. import android.view.MotionEvent;  
  12. import android.widget.ImageView;  
  13.   
  14. /** 
  15.  * 通过手势 缩放图片 左--->右 放大 右 --->左 缩小 速度越快,缩放比例越大 
  16.  */  
  17. public class GestureZoom extends Activity implements OnGestureListener {  
  18.     // 定义手势检测器实例  
  19.     GestureDetector detector;  
  20.     ImageView imageView;  
  21.     // 初始化图片资源  
  22.     Bitmap bitmap;  
  23.     // 定义图片的高和宽  
  24.     int width, height;  
  25.     // 记录当前的缩放比  
  26.     float currentScale = 1;  
  27.     // 控制图片缩放的Matrix对象  
  28.     Matrix matrix;  
  29.   
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.zoom);  
  34.         // 创建手势检测器  
  35.         detector = new GestureDetector(this);  
  36.         imageView = (ImageView) findViewById(R.id.show);  
  37.         matrix = new Matrix();  
  38.         // 获取被缩放的源图片  
  39.         bitmap = BitmapFactory.decodeResource(this.getResources(),  
  40.                 R.drawable.wall);  
  41.         // 获得位图的宽  
  42.         width = bitmap.getWidth();  
  43.         // 获得位图的高  
  44.         height = bitmap.getHeight();  
  45.         // 设置 ImageView初始化显示的图片  
  46.         imageView.setImageBitmap(BitmapFactory.decodeResource(  
  47.                 this.getResources(), R.drawable.wall));  
  48.     }  
  49.   
  50.     @Override  
  51.     public boolean onTouchEvent(MotionEvent event) {  
  52.         // 将该Activity上的触碰时间交个 GestureDetector处理  
  53.         return detector.onTouchEvent(event);  
  54.     }  
  55.   
  56.     @Override  
  57.     public boolean onDown(MotionEvent e) {  
  58.         // TODO Auto-generated method stub  
  59.         return false;  
  60.     }  
  61.   
  62.     @Override  
  63.     public void onShowPress(MotionEvent e) {  
  64.         // TODO Auto-generated method stub  
  65.   
  66.     }  
  67.   
  68.     @Override  
  69.     public boolean onSingleTapUp(MotionEvent e) {  
  70.         return false;  
  71.     }  
  72.   
  73.     @Override  
  74.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,  
  75.             float distanceY) {  
  76.         return false;  
  77.     }  
  78.   
  79.     @Override  
  80.     public void onLongPress(MotionEvent e) {  
  81.   
  82.     }  
  83.   
  84.     @Override  
  85.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
  86.             float velocityY) {  
  87.         velocityX = velocityX > 4000 ? 4000 : velocityX;  
  88.         velocityY = velocityY < -4000 ? -4000 : velocityY;  
  89.         // 感觉手势的速度来计算缩放比,如果 velocityX>0,放大图像,否则缩小图像  
  90.         currentScale += currentScale * velocityX / 4000.0f;  
  91.         // 保证 currentScale 不会等于0  
  92.         currentScale = currentScale > 0.01 ? currentScale : 0.01f;  
  93.         // 重置 Matrix  
  94.         matrix.setScale(currentScale, currentScale, 160, 200);  
  95.         BitmapDrawable tmp = (BitmapDrawable) imageView.getDrawable();  
  96.         // 如果图片还未回收,先强制收回该图片  
  97.         if (!tmp.getBitmap().isRecycled()) {  
  98.             tmp.getBitmap().recycle();  
  99.         }  
  100.         // 根据原始位图和 Matrix创建新图片  
  101.         Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, width, height,  
  102.                 matrix, true);  
  103.         //显示新的位图  
  104.         imageView.setImageBitmap(bitmap2);  
  105.         return true;  
  106.     }  
  107.       
  108. }  

 

查看一下运行的效果

                                                                          

posted @ 2016-03-17 12:28  代码缔造的帝国  阅读(826)  评论(0编辑  收藏  举报