• Android 手势滑动,多点触摸放大缩小图片


    效果展示:

    OUQF8B3]Y9TE@`FPT@}7R8K

    H5S1{3HT8W{$@XCTUX@CE0W

    基本思路

         <1>首先写一个图片控制类ImageControl,实现对图片控制的的基本操作,我们的图片控制类ImageControl是继承自ImageView自定义的视图;

         <2>再写一个测试用的布局,这里就要用到自定义的ImageView;

         <3>编写测试类ImageViewActivity,写onTouchEvent()方法

    图片控制类ImageControl:

      1 package com.basecontrol.view;
      2 
      3 import android.content.Context; 
      4 import android.graphics.Bitmap; 
      5 import android.graphics.Matrix; 
      6 import android.util.AttributeSet; 
      7 import android.util.FloatMath; 
      8 import android.view.MotionEvent; 
      9 import android.widget.ImageView;
     10 
     11 public class ImageControl extends ImageView {
     12 
     13     public ImageControl(Context context) { 
     14         super(context); 
     15     } 
     16     public ImageControl(Context context, AttributeSet attrs) { 
     17         super(context, attrs); 
     18     } 
     19     public ImageControl(Context context, AttributeSet attrs, int defStyle) { 
     20         super(context, attrs, defStyle); 
     21     } 
     22     
     23     Matrix imgMatrix=null;//定义图片的变换矩阵 
     24     
     25     static final int DOUBLE_CLICK_TIME_SPACE=300;//双击时间间隔 
     26     static final int DOUBLE_POINT_DISTANCE =10;// 两点放大两点间最小间距  
     27     static final int NONE = 0; 
     28     private int mode=NONE;//当前模式 
     29     static final int DRAG=1; 
     30     static final int ZOOM = 2; // 放大缩小操作  
     31     
     32     float bigScale=3f;//默认放大倍数 
     33     Boolean isBig=false;//是否放大 
     34     long lastClickTime =0;//单击时间 
     35     float startDistance;//两点触摸两点距离 
     36     float endDistance;//多点触摸两点距离 
     37     
     38     float topHeight;//状态栏高度和标题栏高度 
     39     Bitmap primaryBitmap=null; 
     40     
     41     float contentW;//屏幕内容区宽度 
     42     float contentH;//屏幕内容区高度 
     43     
     44     float primaryW;//原图宽度 
     45     float primaryH;//原图高度 
     46     
     47     float scale; // 适合屏幕缩放倍数  
     48     Boolean isMoveX = true; // 是否允许在X轴拖动  
     49     Boolean isMoveY = true; // 是否允许在Y轴拖动  
     50     float startX;  
     51     float startY;  
     52     float endX;  
     53     float endY;  
     54     float subX;  
     55     float subY;  
     56     float limitX1;  
     57     float limitX2;  
     58     float limitY1;  
     59     float limitY2;  
     60     ICustomMethod mCustomMethod=null; 
     61     /** 
     62      * @param bitmap 要显示的图片 
     63      * @param contentW 内容区域宽度 
     64      * @param contentH 内容区域高度 
     65      * @param topHeight 状态栏高度和标题栏高度之和 
     66      * @param iCustomMethod 
     67      */ 
     68     public void imageInit(Bitmap bitmap,int contentW,int contentH,int topHeight,ICustomMethod iCustomMethod) 
     69     { 
     70         this.primaryBitmap=bitmap; 
     71         this.contentW=contentH; 
     72         this.contentH=contentH; 
     73         this.topHeight=topHeight; 
     74         mCustomMethod=iCustomMethod; 
     75         primaryW=primaryBitmap.getWidth(); 
     76         primaryH=primaryBitmap.getHeight(); 
     77         float scaleX=(float)contentW/primaryW; 
     78         float scaleY=(float)contentH/primaryH; 
     79         scale=scaleX<scaleY?scaleX:scaleY; 
     80         if (scale<1&&1/scale<bigScale) 
     81         { 
     82             bigScale=(float)(1/scale+0.5); 
     83         } 
     84         
     85         imgMatrix=new Matrix(); 
     86         subX = (contentW-primaryW*scale)/2; 
     87         subY=(contentH-primaryH*scale)/2; 
     88         this.setImageBitmap(primaryBitmap); 
     89         this.setScaleType(ScaleType.MATRIX); 
     90         imgMatrix.postScale(scale, scale); 
     91         imgMatrix.postTranslate(subX,subY); 
     92         this.setImageMatrix(imgMatrix); 
     93     } 
     94     /** 
     95      * 按下操作 
     96      * @param event 
     97      */ 
     98     public void mouseDown(MotionEvent event) 
     99     { 
    100         mode=NONE; 
    101         startX=event.getRawX(); 
    102         startY=event.getRawY(); 
    103         if (event.getPointerCount()==1) 
    104         { 
    105             //如果两次时间间隔小于一定值,则默认为双击事件 
    106             if (event.getEventTime()-lastClickTime<DOUBLE_CLICK_TIME_SPACE) 
    107             { 
    108                 changeSize(startX,startY); 
    109             } 
    110             else if (isBig) 
    111             { 
    112                 mode=DRAG; 
    113             } 
    114         } 
    115         lastClickTime=event.getEventTime(); 
    116     } 
    117     /** 
    118      * 非第一个点按下操作 
    119      * @param event 
    120      */ 
    121     public void mousePointDown(MotionEvent event) 
    122     { 
    123         startDistance=getDistance(event); 
    124         if (startDistance > DOUBLE_POINT_DISTANCE) {  
    125             mode = ZOOM;  
    126         } else {  
    127             mode = NONE;  
    128         }  
    129     } 
    130      public void mouseMove(MotionEvent event) 
    131      {  
    132         if ((mode == DRAG) && (isMoveX || isMoveY)) {  
    133             float[] XY = getTranslateXY(imgMatrix);  
    134             float transX = 0;  
    135             float transY = 0;  
    136             if (isMoveX) {  
    137                 endX = event.getRawX();  
    138                 transX = endX - startX;  
    139                 if ((XY[0] + transX) <= limitX1) {  
    140                     transX = limitX1 - XY[0];  
    141                 }  
    142                 if ((XY[0] + transX) >= limitX2) {  
    143                     transX = limitX2 - XY[0];  
    144                 }  
    145             }  
    146             if (isMoveY) {  
    147                 endY = event.getRawY();  
    148                 transY = endY - startY;  
    149                 if ((XY[1] + transY) <= limitY1) {  
    150                     transY = limitY1 - XY[1];  
    151                 }  
    152                 if ((XY[1] + transY) >= limitY2) {  
    153                     transY = limitY2 - XY[1];  
    154                 }  
    155             }  
    156   
    157             imgMatrix.postTranslate(transX, transY);  
    158             startX = endX;  
    159             startY = endY;  
    160             this.setImageMatrix(imgMatrix);  
    161         } else if (mode == ZOOM && event.getPointerCount() > 1) {  
    162             endDistance = getDistance(event);  
    163             float dif = endDistance - startDistance;  
    164             if (Math.abs(endDistance - startDistance) > DOUBLE_POINT_DISTANCE) {  
    165                 if (isBig) {  
    166                     if (dif < 0) {  
    167                         changeSize(0, 0);  
    168                         mode = NONE;  
    169                     }  
    170                 } else if (dif > 0) {  
    171                     float x = event.getX(0) / 2 + event.getX(1) / 2;  
    172                     float y = event.getY(0) / 2 + event.getY(1) / 2;  
    173                     changeSize(x, y);  
    174                     mode = NONE;  
    175                 }  
    176             }  
    177         }  
    178     } 
    179      /** 
    180       * 鼠标抬起事件 
    181       */ 
    182     public void mouseUp() 
    183     {  
    184         mode = NONE;  
    185     }  
    186     private void changeSize(float x, float y) {  
    187         if (isBig) {  
    188             // 如果处于最大状态,则还原  
    189             imgMatrix.reset();  
    190             imgMatrix.postScale(scale, scale);  
    191             imgMatrix.postTranslate(subX, subY);  
    192             isBig = false;  
    193         } else {  
    194             imgMatrix.postScale(bigScale, bigScale); // 在原有矩阵后乘放大倍数  
    195             float transX = -((bigScale - 1) * x);  
    196             float transY = -((bigScale - 1) * (y - topHeight)); // (bigScale-1)(y-statusBarHeight-subY)+2*subY;  
    197             float currentWidth = primaryW * scale * bigScale; // 放大后图片大小  
    198             float currentHeight = primaryH * scale * bigScale;  
    199             // 如果图片放大后超出屏幕范围处理  
    200             if (currentHeight > contentH) {  
    201                 limitY1 = -(currentHeight - contentH); // 平移限制  
    202                 limitY2 = 0;  
    203                 isMoveY = true; // 允许在Y轴上拖动  
    204                 float currentSubY = bigScale * subY; // 当前平移距离  
    205                 // 平移后,内容区域上部有空白处理办法  
    206                 if (-transY < currentSubY) {  
    207                     transY = -currentSubY;  
    208                 }  
    209                 // 平移后,内容区域下部有空白处理办法  
    210                 if (currentSubY + transY < limitY1) {  
    211                     transY = -(currentHeight + currentSubY - contentH);  
    212                 }  
    213             } else {  
    214                 // 如果图片放大后没有超出屏幕范围处理,则不允许拖动  
    215                 isMoveY = false;  
    216             }  
    217   
    218             if (currentWidth > contentW) {  
    219                 limitX1 = -(currentWidth - contentW);  
    220                 limitX2 = 0;  
    221                 isMoveX = true;  
    222                 float currentSubX = bigScale * subX;  
    223                 if (-transX < currentSubX) {  
    224                     transX = -currentSubX;  
    225                 }  
    226                 if (currentSubX + transX < limitX1) {  
    227                     transX = -(currentWidth + currentSubX - contentW);  
    228                 }  
    229             } else {  
    230                 isMoveX = false;  
    231             }  
    232   
    233             imgMatrix.postTranslate(transX, transY);  
    234             isBig = true;  
    235         }  
    236   
    237         this.setImageMatrix(imgMatrix);  
    238         if (mCustomMethod != null) {  
    239             mCustomMethod.customMethod(isBig);  
    240         }  
    241     }  
    242     /** 
    243      * 获取变换矩阵中X轴偏移量和Y轴偏移量 
    244      * @param matrix 
    245      * @return 
    246      */ 
    247     private float[] getTranslateXY(Matrix matrix) 
    248     {  
    249         float[] values = new float[9];  
    250         matrix.getValues(values);  
    251         float[] floats = new float[2];  
    252         floats[0] = values[Matrix.MTRANS_X];  
    253         floats[1] = values[Matrix.MTRANS_Y];  
    254         return floats;  
    255     } 
    256     /** 
    257      * 获取两点间距离 
    258      * @param event 
    259      * @return 
    260      */ 
    261     private float getDistance(MotionEvent event) 
    262     {  
    263         float x = event.getX(0) - event.getX(1);  
    264         float y = event.getY(0) - event.getY(1);  
    265         return FloatMath.sqrt(x * x + y * y);  
    266     }  
    267     /** 
    268      * 用户自定义方法 
    269      * @author AILALA 
    270      */ 
    271     public interface ICustomMethod 
    272     { 
    273         public void customMethod(Boolean currentStatus); 
    274     } 
    275 }
    ImageControl

    测试布局:

     1 <?xml version="1.0" encoding="utf-8"?> 
     2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     3     android:layout_width="match_parent" 
     4     android:layout_height="match_parent" > 
     5     
     6     <com.basecontrol.view.ImageControl 
     7         android:id="@+id/common_imageview_imageControll" 
     8         android:layout_width="fill_parent" 
     9         android:layout_height="fill_parent" 
    10         android:src="@drawable/ic_launcher"/>
    11 
    12     <LinearLayout 
    13         android:id="@+id/common_iamgeview_llTitle" 
    14         android:layout_width="wrap_content" 
    15         android:layout_height="wrap_content" 
    16         android:layout_alignParentLeft="true" 
    17         android:layout_alignParentTop="true" > 
    18   
    19         <TextView 
    20             android:id="@+id/common_imageview_title" 
    21             android:layout_width="fill_parent" 
    22             android:layout_height="wrap_content" 
    23             android:text="报告"/> 
    24     </LinearLayout> 
    25 </RelativeLayout>
    View Code

    测试的Activity:

     1 package com.basecontrol.ui;
     2 
     3 import com.basecontrol.view.ImageControl; 
     4 import com.basecontrol.view.ImageControl.ICustomMethod; 
     5 import com.example.basecontrol.R; 
     6 import android.app.Activity; 
     7 import android.graphics.Bitmap; 
     8 import android.graphics.Rect; 
     9 import android.graphics.drawable.BitmapDrawable; 
    10 import android.os.Bundle; 
    11 import android.view.MotionEvent; 
    12 import android.view.View; 
    13 import android.widget.LinearLayout; 
    14 import android.widget.TextView; 
    15 import android.widget.Toast;
    16 
    17 public class ImageViewActivity extends Activity 
    18 {
    19 
    20     @Override 
    21     protected void onCreate(Bundle savedInstanceState) { 
    22         super.onCreate(savedInstanceState); 
    23         setContentView(R.layout.bc_common_image_view); 
    24         findView(); 
    25     } 
    26     
    27     public void onWindowFocusChanged(boolean hasFocus) 
    28     { 
    29         super.onWindowFocusChanged(hasFocus); 
    30         init(); 
    31     }; 
    32     
    33     ImageControl imgControl; 
    34     LinearLayout llTitle; 
    35     TextView tvTitle; 
    36     private void findView() 
    37     { 
    38         imgControl=(ImageControl) findViewById(R.id.common_imageview_imageControll); 
    39         llTitle=(LinearLayout) findViewById(R.id.common_iamgeview_llTitle); 
    40         tvTitle=(TextView) findViewById(R.id.common_imageview_title); 
    41     } 
    42     
    43     private void init() { 
    44         tvTitle.setText("图片测试");  
    45         // 这里可以为imgcontrol的图片路径动态赋值  
    46         // ............  
    47           
    48         Bitmap bmp;  
    49         if (imgControl.getDrawingCache() != null) {  
    50             bmp = Bitmap.createBitmap(imgControl.getDrawingCache());  
    51         } else {  
    52             bmp = ((BitmapDrawable)imgControl.getDrawable()).getBitmap();  
    53         }  
    54         Rect frame = new Rect();  
    55         getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);  
    56         int statusBarHeight = frame.top;  
    57         int screenW = this.getWindowManager().getDefaultDisplay().getWidth();  
    58         int screenH = this.getWindowManager().getDefaultDisplay().getHeight()  
    59                 - statusBarHeight;  
    60         if (bmp != null) {  
    61             imgControl.imageInit(bmp, screenW, screenH, statusBarHeight,  
    62                     new ICustomMethod() {  
    63                         @Override 
    64                         public void customMethod(Boolean currentStatus) {  
    65                             // 当图片处于放大或缩小状态时,控制标题是否显示  
    66                             if (currentStatus) {  
    67                                 llTitle.setVisibility(View.GONE);  
    68                             } else {  
    69                                 llTitle.setVisibility(View.VISIBLE);  
    70                             }  
    71                         } 
    72                     });  
    73         }  
    74         else  
    75         {  
    76             Toast.makeText(ImageViewActivity.this, "图片加载失败,请稍候再试!", Toast.LENGTH_SHORT)  
    77                     .show();  
    78         }  
    79   
    80     } 
    81     @Override 
    82     public boolean onTouchEvent(MotionEvent event) { 
    83         switch (event.getAction()&MotionEvent.ACTION_MASK) { 
    84         case MotionEvent.ACTION_DOWN: 
    85             imgControl.mouseDown(event); 
    86             break; 
    87         case MotionEvent.ACTION_POINTER_DOWN: 
    88             imgControl.mousePointDown(event); 
    89             break; 
    90         case MotionEvent.ACTION_MOVE: 
    91             imgControl.mouseMove(event); 
    92             break; 
    93         case MotionEvent.ACTION_UP: 
    94             imgControl.mouseUp(); 
    95             break; 
    96         } 
    97         return super.onTouchEvent(event); 
    98     } 
    99 }
    ImageViewActivity

    嗯,就酱…………

  • 相关阅读:
    Unity 摄像机Clear Flags和Culling Mask属性用途详解
    Unity 坐标系
    Unity 模型导入导出
    Unity 序列化
    正确理解静态Static关键字
    Unity 中的协同程序
    Asp.Net中调用存储过程并返回输出参数
    php学习知识点
    Jauery 中Ajax的几种异步请求
    2014年12月21号面试
  • 原文地址:https://www.cnblogs.com/wucaiyun1/p/4910934.html
Copyright © 2020-2023  润新知