Android App中实现可以双击放大和缩小图片功能的实例

Android App中实现可以双击放大和缩小图片功能的实例,第1张

概述先来看一个很简单的核心图片缩放方法:publicstaticBitmapscale(Bitmapbitmap,floatscaleWidth,floatscaleHeight){

先来看一个很简单的核心图片缩放方法:

public static Bitmap scale(Bitmap bitmap,float scaleWIDth,float scaleHeight) {   int wIDth = bitmap.getWIDth();   int height = bitmap.getHeight();   Matrix matrix = new Matrix();   matrix.postscale(scaleWIDth,scaleHeight);   Log.i(TAG,"scaleWIDth:"+ scaleWIDth +",scaleHeight:"+ scaleHeight);   return Bitmap.createBitmap(bitmap,wIDth,height,matrix,true); } 

注意要比例设置正确否则可能会内存溢出,比如曾经使用图片缩放时遇到这么个问题:

java.lang.IllegalArgumentException: bitmap size exceeds 32bits

后来一行行查代码,发现原来是 scale 的比例计算错误,将原图给放大了 20 多倍,导致内存溢出所致,重新修改比例值后就正常了。

好了,下面真正来看一下这个实现了放大和原大两个级别的缩放的模块。
功能有:

以触摸点为中心放大(这个是网上其他的代码没有的) 边界控制(这个是网上其他的代码没有的) 双击放大或缩小(主要考虑到电阻屏) 多点触摸放大和缩小

这个模块已经通过了测试,并且用户也使用有一段时间了,是属于比较稳定的了。

下面贴上代码及使用方法(没有写测试项目,大家见谅):

ImageControl 类似一个用户自定义的ImageVIEw控件。用法将在下面的代码中贴出。

import androID.content.Context; import androID.graphics.Bitmap; import androID.graphics.Matrix; import androID.util.AttributeSet; import androID.util.floatMath; import androID.vIEw.MotionEvent; import androID.Widget.ImageVIEw;  public class ImageControl extends ImageVIEw {   public ImageControl(Context context) {     super(context);     // Todo auto-generated constructor stub   }    public ImageControl(Context context,AttributeSet attrs) {     super(context,attrs);     // Todo auto-generated constructor stub   }    public ImageControl(Context context,AttributeSet attrs,int defStyle) {     super(context,attrs,defStyle);     // Todo auto-generated constructor stub   }    // ImageVIEw img;   Matrix imgMatrix = null; // 定义图片的变换矩阵    static final int DOUBLE_CliCK_TIME_SPACE = 300; // 双击时间间隔   static final int DOUBLE_POINT_disTANCE = 10; // 两点放大两点间最小间距   static final int NONE = 0;   static final int DRAG = 1; // 拖动 *** 作   static final int ZOOM = 2; // 放大缩小 *** 作   private int mode = NONE; // 当前模式    float bigScale = 3f; // 默认放大倍数   Boolean isBig = false; // 是否是放大状态   long lastClickTime = 0; // 单击时间   float startdistance; // 多点触摸两点距离   float enddistance; // 多点触摸两点距离    float topHeight; // 状态栏高度和标题栏高度   Bitmap primaryBitmap = null;    float contentW; // 屏幕内容区宽度   float contentH; // 屏幕内容区高度    float primaryW; // 原图宽度   float primaryH; // 原图高度    float scale; // 适合屏幕缩放倍数   Boolean isMoveX = true; // 是否允许在X轴拖动   Boolean isMoveY = true; // 是否允许在Y轴拖动   float startX;   float startY;   float endX;   float endY;   float subX;   float subY;   float limitX1;   float limitX2;   float limitY1;   float limitY2;   ICustomMethod mCustomMethod = null;    /**    * 初始化图片    *    * @param bitmap    *      要显示的图片    * @param contentW    *      内容区域宽度    * @param contentH    *      内容区域高度    * @param topHeight    *      状态栏高度和标题栏高度之和    */   public voID imageInit(Bitmap bitmap,int contentW,int contentH,int topHeight,ICustomMethod iCustomMethod) {     this.primaryBitmap = bitmap;     this.contentW = contentW;     this.contentH = contentH;     this.topHeight = topHeight;     mCustomMethod = iCustomMethod;     primaryW = primaryBitmap.getWIDth();     primaryH = primaryBitmap.getHeight();     float scaleX = (float) contentW / primaryW;     float scaleY = (float) contentH / primaryH;     scale = scaleX < scaleY ? scaleX : scaleY;     if (scale < 1 && 1 / scale < bigScale) {       bigScale = (float) (1 / scale + 0.5);     }      imgMatrix = new Matrix();     subX = (contentW - primaryW * scale) / 2;     subY = (contentH - primaryH * scale) / 2;     this.setimageBitmap(primaryBitmap);     this.setScaleType(ScaleType.MATRIX);     imgMatrix.postscale(scale,scale);     imgMatrix.postTranslate(subX,subY);     this.setimageMatrix(imgMatrix);   }    /**    * 按下 *** 作    *    * @param event    */   public voID mouseDown(MotionEvent event) {     mode = NONE;     startX = event.getRawX();     startY = event.getRawY();     if (event.getPointerCount() == 1) {       // 如果两次点击时间间隔小于一定值,则默认为双击事件       if (event.getEventTime() - lastClickTime < DOUBLE_CliCK_TIME_SPACE) {         changeSize(startX,startY);       } else if (isBig) {         mode = DRAG;       }     }      lastClickTime = event.getEventTime();   }    /**    * 非第一个点按下 *** 作    *    * @param event    */   public voID mousePointDown(MotionEvent event) {     startdistance = getdistance(event);     if (startdistance > DOUBLE_POINT_disTANCE) {       mode = ZOOM;     } else {       mode = NONE;     }   }    /**    * 移动 *** 作    *    * @param event    */   public voID mouseMove(MotionEvent event) {     if ((mode == DRAG) && (isMoveX || isMoveY)) {       float[] XY = getTranslateXY(imgMatrix);       float transX = 0;       float transY = 0;       if (isMoveX) {         endX = event.getRawX();         transX = endX - startX;         if ((XY[0] + transX) <= limitX1) {           transX = limitX1 - XY[0];         }         if ((XY[0] + transX) >= limitX2) {           transX = limitX2 - XY[0];         }       }       if (isMoveY) {         endY = event.getRawY();         transY = endY - startY;         if ((XY[1] + transY) <= limitY1) {           transY = limitY1 - XY[1];         }         if ((XY[1] + transY) >= limitY2) {           transY = limitY2 - XY[1];         }       }        imgMatrix.postTranslate(transX,transY);       startX = endX;       startY = endY;       this.setimageMatrix(imgMatrix);     } else if (mode == ZOOM && event.getPointerCount() > 1) {       enddistance = getdistance(event);       float dif = enddistance - startdistance;       if (Math.abs(enddistance - startdistance) > DOUBLE_POINT_disTANCE) {         if (isBig) {           if (dif < 0) {             changeSize(0,0);             mode = NONE;           }         } else if (dif > 0) {           float x = event.getX(0) / 2 + event.getX(1) / 2;           float y = event.getY(0) / 2 + event.getY(1) / 2;           changeSize(x,y);           mode = NONE;         }       }     }   }    /**    * 鼠标抬起事件    */   public voID mouseUp() {     mode = NONE;   }    /**    * 图片放大缩小    *    * @param x    *      点击点X坐标    * @param y    *      点击点Y坐标    */   private voID changeSize(float x,float y) {     if (isBig) {       // 如果处于最大状态,则还原       imgMatrix.reset();       imgMatrix.postscale(scale,scale);       imgMatrix.postTranslate(subX,subY);       isBig = false;     } else {       imgMatrix.postscale(bigScale,bigScale); // 在原有矩阵后乘放大倍数       float transX = -((bigScale - 1) * x);       float transY = -((bigScale - 1) * (y - topHeight)); // (bigScale-1)(y-statusbarHeight-subY)+2*subY;       float currentWIDth = primaryW * scale * bigScale; // 放大后图片大小       float currentHeight = primaryH * scale * bigScale;       // 如果图片放大后超出屏幕范围处理       if (currentHeight > contentH) {         limitY1 = -(currentHeight - contentH); // 平移限制         limitY2 = 0;         isMoveY = true; // 允许在Y轴上拖动         float currentSubY = bigScale * subY; // 当前平移距离         // 平移后,内容区域上部有空白处理办法         if (-transY < currentSubY) {           transY = -currentSubY;         }         // 平移后,内容区域下部有空白处理办法         if (currentSubY + transY < limitY1) {           transY = -(currentHeight + currentSubY - contentH);         }       } else {         // 如果图片放大后没有超出屏幕范围处理,则不允许拖动         isMoveY = false;       }        if (currentWIDth > contentW) {         limitX1 = -(currentWIDth - contentW);         limitX2 = 0;         isMoveX = true;         float currentSubX = bigScale * subX;         if (-transX < currentSubX) {           transX = -currentSubX;         }         if (currentSubX + transX < limitX1) {           transX = -(currentWIDth + currentSubX - contentW);         }       } else {         isMoveX = false;       }        imgMatrix.postTranslate(transX,transY);       isBig = true;     }      this.setimageMatrix(imgMatrix);     if (mCustomMethod != null) {       mCustomMethod.customMethod(isBig);     }   }    /**    * 获取变换矩阵中X轴偏移量和Y轴偏移量    *    * @param matrix    *      变换矩阵    * @return    */   private float[] getTranslateXY(Matrix matrix) {     float[] values = new float[9];     matrix.getValues(values);     float[] floats = new float[2];     floats[0] = values[Matrix.MTRANS_X];     floats[1] = values[Matrix.MTRANS_Y];     return floats;   }    /**    * 获取两点间的距离    *    * @param event    * @return    */   private float getdistance(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);   }    /**    * @author administrator 用户自定义方法    */   public interface ICustomMethod {     public voID customMethod(Boolean currentStatus);   } } 

 

ImageVewActivity 这个用于测试的Activity

import androID.app.Activity; import androID.graphics.Bitmap; import androID.graphics.Rect; import androID.graphics.drawable.BitmapDrawable; import androID.os.Bundle; import androID.vIEw.MotionEvent; import androID.vIEw.VIEw; import androID.Widget.linearLayout; import androID.Widget.TextVIEw; import androID.Widget.Toast; import ejiang.boiler.ImageControl.ICustomMethod; import ejiang.boiler.R.ID;  public class ImageVIEwActivity extends Activity {    @OverrIDe   protected voID onCreate(Bundle savedInstanceState) {     // Todo auto-generated method stub     super.onCreate(savedInstanceState);     setContentVIEw(R.layout.common_image_vIEw);     findVIEw();   }    public voID onWindowFocusChanged(boolean hasFocus) {     super.onWindowFocusChanged(hasFocus);     init();   }    ImageControl imgControl;   linearLayout llTitle;   TextVIEw tvTitle;    private voID findVIEw() {     imgControl = (ImageControl) findVIEwByID(ID.common_imagevIEw_imageControl1);     llTitle = (linearLayout) findVIEwByID(ID.common_imagevIEw_llTitle);     tvTitle = (TextVIEw) findVIEwByID(ID.common_imagevIEw_Title);   }    private voID init() {     tvTitle.setText("图片测试");     // 这里可以为imgcontrol的图片路径动态赋值     // ............          Bitmap bmp;     if (imgControl.getDrawingCache() != null) {       bmp = Bitmap.createBitmap(imgControl.getDrawingCache());     } else {       bmp = ((BitmapDrawable) imgControl.getDrawable()).getBitmap();     }     Rect frame = new Rect();     getwindow().getDecorVIEw().getwindowVisibledisplayFrame(frame);     int statusbarHeight = frame.top;     int screenW = this.getwindowManager().getDefaultdisplay().getWIDth();     int screenH = this.getwindowManager().getDefaultdisplay().getHeight()         - statusbarHeight;     if (bmp != null) {       imgControl.imageInit(bmp,screenW,screenH,statusbarHeight,new ICustomMethod() {                         @OverrIDe             public voID customMethod(Boolean currentStatus) {               // 当图片处于放大或缩小状态时,控制标题是否显示               if (currentStatus) {                 llTitle.setVisibility(VIEw.GONE);               } else {                 llTitle.setVisibility(VIEw.VISIBLE);               }             }           });     }     else     {       Toast.makeText(ImageVIEwActivity.this,"图片加载失败,请稍候再试!",Toast.LENGTH_SHORT)           .show();     }    }    @OverrIDe   public boolean ontouchEvent(MotionEvent event) {     switch (event.getAction() & MotionEvent.ACTION_MASK) {     case MotionEvent.ACTION_DOWN:       imgControl.mouseDown(event);             break;      /**      * 非第一个点按下      */     case MotionEvent.ACTION_POINTER_DOWN:              imgControl.mousePointDown(event);            break;     case MotionEvent.ACTION_MOVE:         imgControl.mouseMove(event);              break;      case MotionEvent.ACTION_UP:       imgControl.mouseUp();       break;      }      return super.ontouchEvent(event);   } } 

        在上面的代码中,需要注意两点。一Activity中要重写ontouchEvent方法,将触摸事件传递到ImageControl,这点类似于WPF中的路由事件机制。二初始化imgControl即imgControl.imageInit,注意其中的参数。最后一个参数类似于C#中的委托,我这里使用接口来实现,在放大缩小的切换时要执行的 *** 作都卸载这个方法中。


common_image_vIEw.xml  布局文件

<?xml version="1.0" enCoding="utf-8"?> <relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"   androID:ID="@+ID/rl"   androID:layout_wIDth="fill_parent"   androID:layout_height="fill_parent" >    <ejiang.boiler.ImageControl     androID:ID="@+ID/common_imagevIEw_imageControl1"     androID:layout_wIDth="fill_parent"     androID:layout_height="fill_parent"     androID:src="@drawable/ic_launcher" />    <linearLayout     androID:ID="@+ID/common_imagevIEw_llTitle"          androID:layout_alignParentleft="true"     androID:layout_alignParenttop="true" >      <TextVIEw       androID:ID="@+ID/common_imagevIEw_Title"              androID:layout_wIDth="fill_parent"       androID:layout_height="wrap_content"       androID:layout_weight="1"       androID:text="报告" />   </linearLayout>  </relativeLayout> 

总结

以上是内存溢出为你收集整理的Android App中实现可以双击放大和缩小图片功能实例全部内容,希望文章能够帮你解决Android App中实现可以双击放大和缩小图片功能的实例所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1149521.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存